go-viee-fetch-Demo/src/packages/components/Charts/HazardousChemicalsSpace/AlarmListHazC/index.vue

252 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<SmallBorder class="SmallBorder">
<div class="go-alarm-list">
<div class="header">
<div class="title">
<div class="title-text">
<span :style="{
color: option.titleColor,
fontSize: option.titleSize + 'px',
fontWeight: option.fontWeight,
fontStyle: option.fontStyle,
marginLeft: option.paddingX + 'px',
marginTop: option.paddingY + 'px',
letterSpacing: option.letterSpacing + 'px'
}">{{ option.title }}</span>
</div>
</div>
<div v-if="option.isShowButton" class="header-right-squares">
<div class="square" style="background-color: #2e69e0"></div>
<div class="square" style="background-color: #2e9bf0"></div>
<div class="square" style="background-color: #2ef0b3"></div>
</div>
</div>
<div class="table-header" :style="{
height: option.headerHeight + 'px'
}">
<div v-for="header in option.header" :key="header" class="header-item"
:style="{ color: option.headerTextColor, fontSize: option.fontSize + 'px' }">
{{ header }}
</div>
</div>
<div class="table-body">
<div v-if="isLoading" style="display: flex; width: 100%; justify-content: center; margin-top: 16px">
<n-spin size="large" />
</div>
<div v-for="(item, index) in option.dataset" :key="index" class="table-row"
:style="{ backgroundColor: option.itemBackgroundColor, height: option.itemHeight + 'px' }">
<div class="row-item" :style="{ color: option.textColor, fontSize: option.fontSize + 'px' }">
{{ item.alarmDescname }}
</div>
<div class="row-item" :style="{ color: option.textColor, fontSize: option.fontSize + 'px' }">
{{ item.alarmTime }}
</div>
<div class="row-item" :style="{ color: option.textColor, fontSize: option.fontSize + 'px' }">
{{ item.compName }}
</div>
<div class="row-item" :style="{ color: getStatusColor(item.alarmLevel), fontSize: option.fontSize + 'px' }">
{{ item.alarmLevel }}
</div>
</div>
</div>
</div>
</SmallBorder>
</template>
<script setup lang="ts">
import { PropType, computed, ref, onMounted, onUnmounted } from 'vue'
import { option as configOption } from './config'
import SmallBorder from '../SmallBorder/index.vue'
import axiosInstance from '@/api/axios'
const props = defineProps({
chartConfig: {
type: Object as PropType<{ option: typeof configOption }>,
required: true
}
})
const isLoading = ref(false)
const option = computed(() => props.chartConfig.option)
const getStatusColor = (status: string) => {
return (props.chartConfig.option.statusColors as Record<string, string>)[status] || '#ffffff'
}
const convertTimestampToDateTime = (timestamp: number | string) => {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
const seconds = date.getSeconds().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}`
}
const fetchRecentAlarms = async () => {
try {
const res: any = await axiosInstance({
method: 'GET',
url: `/space/getRecentAlarms`,
responseType: 'json'
});
if (res && res?.value) {
let rawData = [];
if (Array.isArray(res.value.items)) {
rawData = res.value.items;
} else if (Array.isArray(res.value)) {
rawData = res.value;
}
const formattedData = rawData.map((item: any) => {
let newAlarmDescname = item.alarmDescname;
const dateTimeRegexInDesc = /于\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
if (newAlarmDescname) {
newAlarmDescname = newAlarmDescname.replace(dateTimeRegexInDesc, '');
}
return {
...item,
alarmTime: convertTimestampToDateTime(item.alarmTime), // 格式化 alarmTime
alarmDescname: newAlarmDescname // 更新 alarmDescname移除时间部分
};
});
option.value.dataset = formattedData; // 更新 option 的 dataset
} else {
console.warn('API返回数据格式不符合预期:', res);
option.value.dataset = [];
}
} catch (error) {
console.error('获取最近报警数据失败:', error);
option.value.dataset = [];
} finally {
isLoading.value = false;
}
};
let alarmTimer: any = null;
onMounted(() => {
fetchRecentAlarms();
// 每5分钟执行一次
const interval = 5 * 60 * 1000;
alarmTimer = setInterval(fetchRecentAlarms, interval);
});
onUnmounted(() => {
clearInterval(alarmTimer);
});
</script>
<style lang="scss" scoped>
.SmallBorder {
position: relative;
// background-color: #ffffff;
}
.go-alarm-list {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
color: #ffffff;
padding: 12px;
margin-top: 5px;
box-sizing: border-box;
// background-color: #4da6ff;
z-index: 10;
.header {
display: flex;
justify-content: space-between;
align-items: center;
.title {
display: flex;
align-items: center;
.title-text {
height: 35px;
display: flex;
align-items: center;
padding: 0 20px 0 20px;
}
}
.header-right-squares {
display: flex;
align-items: center;
.square {
width: 10px;
height: 10px;
margin-left: 5px;
}
}
}
.table-header {
display: flex;
align-items: center;
padding: 0 10px;
background: linear-gradient(to top, #226493c8, #0f2448);
border-bottom: 2px solid #4da6ff;
margin-top: 10px;
.header-item {
flex: 1 0 25%;
margin-right: 1.5em;
text-align: left;
}
}
.table-body {
flex: 1;
overflow-y: auto;
&::-webkit-scrollbar {
display: none;
/* 隐藏滚动条 */
width: 0;
height: 0;
}
scrollbar-width: none;
.table-row {
display: flex;
align-items: center;
padding: 0 10px;
margin-bottom: 4px;
&:first-child {
margin-top: 5px;
}
&:last-child {
margin-bottom: 0;
}
.row-item {
flex: 1 0 25%;
margin-right: 1.5em;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
</style>