style:大屏-“今日开机率/稼动率”模块对接接口

main
黄伟杰 1 week ago
parent 141126ea2c
commit f4d3a4de82

@ -8,8 +8,14 @@ export interface DeviceOperationRecordVO {
totalStandbyTime: number
totalFaultTime: number
totalWarningTime: number
totalOfflineTime?: number
utilizationRate: string
powerOnRate?: string
startTime?: string
endTime?: string
lineCode?: string
lineName?: string
deviceId?: number
}
export interface DeviceOperationRecordPageParams {
@ -22,10 +28,23 @@ export interface DeviceOperationRecordPageParams {
ids?: string
}
export interface DeviceOperationListParams {
deviceCode?: string
deviceName?: string
startTime?: string
endTime?: string
lineCode?: string
lineName?: string
deviceId?: number | string
}
export const DeviceOperationRecordApi = {
getDeviceOperationRecordPage: async (params: DeviceOperationRecordPageParams) => {
return await request.get({ url: `/iot/device-operation-record/deviceOperationPage`, params })
},
getDeviceOperationList: async (params?: DeviceOperationListParams) => {
return await request.get({ url: `/iot/device-operation-record/deviceOperationList`, params })
},
exportDeviceOperationReport: async (params: DeviceOperationRecordPageParams) => {
return await request.download({ url: `/iot/device-operation-record/export-device-operation-report`, params })
}

@ -17,23 +17,59 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import dayjs from 'dayjs'
import { useChart, colors } from '../utils'
import { DeviceOperationRecordApi, type DeviceOperationRecordVO } from '@/api/iot/deviceOperationRecord'
const { init, instance } = useChart('chart-today')
const lineMetrics = [
{ name: '产线A', run: 88, avail: 82 },
{ name: '产线B', run: 86, avail: 80 },
{ name: '产线C', run: 90, avail: 84 },
{ name: '产线D', run: 85, avail: 79 },
{ name: '产线E', run: 87, avail: 81 },
{ name: '产线F', run: 92, avail: 86 }
]
type LineMetric = { name: string; run: number; avail: number }
const lineMetrics = ref<LineMetric[]>([])
const currentLineName = ref(lineMetrics[0].name)
const currentLineName = ref('')
let timer: ReturnType<typeof setInterval> | null = null
let currentLineIndex = 0
const toRateNumber = (value: unknown) => {
if (typeof value === 'number') {
if (!Number.isFinite(value)) return 0
if (value >= 0 && value <= 1) return Math.round(value * 10000) / 100
return Math.max(0, Math.min(100, Math.round(value * 100) / 100))
}
const raw = String(value ?? '').trim()
if (!raw) return 0
const numeric = Number(raw.replace(/[^\d.+-]/g, ''))
if (!Number.isFinite(numeric)) return 0
if (raw.includes('%')) return Math.max(0, Math.min(100, Math.round(numeric * 100) / 100))
if (numeric >= 0 && numeric <= 1) return Math.round(numeric * 10000) / 100
return Math.max(0, Math.min(100, Math.round(numeric * 100) / 100))
}
const buildLineMetrics = (rows: DeviceOperationRecordVO[]) => {
const groupMap = new Map<string, { name: string; power: number[]; util: number[] }>()
rows.forEach((row) => {
const name = String((row as any)?.lineName ?? (row as any)?.lineCode ?? row.deviceName ?? row.deviceCode ?? '').trim()
if (!name) return
const power = toRateNumber((row as any)?.powerOnRate)
const util = toRateNumber((row as any)?.utilizationRate)
const key = name
if (!groupMap.has(key)) {
groupMap.set(key, { name, power: [], util: [] })
}
const g = groupMap.get(key)!
if (Number.isFinite(power)) g.power.push(power)
if (Number.isFinite(util)) g.util.push(util)
})
const avg = (arr: number[]) => (arr.length ? arr.reduce((s, v) => s + v, 0) / arr.length : 0)
const list = Array.from(groupMap.values()).map((g) => ({
name: g.name,
run: Math.round(avg(g.power) * 100) / 100,
avail: Math.round(avg(g.util) * 100) / 100
}))
list.sort((a, b) => a.name.localeCompare(b.name))
return list
}
const gaugeOption = (run: number, avail: number) => {
return {
backgroundColor: 'transparent',
@ -80,25 +116,56 @@ const gaugeOption = (run: number, avail: number) => {
}
}
onMounted(() => {
const chart = init()
if (!chart) return
const renderCurrent = () => {
const list = lineMetrics.value
if (!list.length) {
currentLineName.value = '暂无数据'
const c = instance()
if (c) c.setOption(gaugeOption(0, 0))
return
}
const idx = Math.max(0, Math.min(list.length - 1, currentLineIndex))
const item = list[idx]
currentLineName.value = item.name
const c = instance()
if (c) c.setOption(gaugeOption(item.run, item.avail))
}
// Initial render
chart.setOption(gaugeOption(lineMetrics[0].run, lineMetrics[0].avail))
const loadTodayOps = async () => {
const res = await DeviceOperationRecordApi.getDeviceOperationList({})
const rawList = Array.isArray(res) ? res : (res as any)?.list || (res as any)?.data || []
const list = Array.isArray(rawList) ? (rawList as DeviceOperationRecordVO[]) : []
lineMetrics.value = buildLineMetrics(list)
currentLineIndex = 0
renderCurrent()
}
// Start rotation
const startRotate = () => {
if (timer) clearInterval(timer)
timer = null
if (lineMetrics.value.length <= 1) return
timer = setInterval(() => {
currentLineIndex = (currentLineIndex + 1) % lineMetrics.length
const item = lineMetrics[currentLineIndex]
currentLineName.value = item.name
const list = lineMetrics.value
if (!list.length) return
currentLineIndex = (currentLineIndex + 1) % list.length
renderCurrent()
}, 8000)
}
// Update chart
const c = instance()
if (c) {
c.setOption(gaugeOption(item.run, item.avail))
}
}, 3000)
onMounted(async () => {
const chart = init()
if (!chart) return
chart.setOption(gaugeOption(0, 0))
try {
await loadTodayOps()
} catch (e) {
console.error('Failed to load today ops:', e)
lineMetrics.value = []
currentLineIndex = 0
renderCurrent()
}
startRotate()
})
onUnmounted(() => {

Loading…
Cancel
Save