forked from gzt/A8000
7 changed files with 112 additions and 141 deletions
-
3components.d.ts
-
129src/components/AlarmLight.vue
-
7src/components/dialogs/AlarmDetailByType.vue
-
3src/components/dialogs/AlarmModal.vue
-
67src/components/dialogs/AlarmRecordModal.vue
-
1src/pages/Index/Index.vue
-
43src/pages/Index/Regular/Running.vue
@ -1,129 +0,0 @@ |
|||||
<template> |
|
||||
<div class="alarm-light-container" @click="onShowAlarmDetail"> |
|
||||
<div |
|
||||
class="alarm-light" |
|
||||
:style="{ '--light-color': getColor }" |
|
||||
:class="{ 'pulse-animation': isActive }" |
|
||||
> |
|
||||
<span class="light-text">{{ text }}</span> |
|
||||
</div> |
|
||||
<el-dialog v-model="detailVisible" width="700" style="z-index: 999"> |
|
||||
<AlarmDetailByType :currEventReport="alarmItem"/> |
|
||||
</el-dialog> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { defineProps, computed, ref } from 'vue'; |
|
||||
import AlarmDetailByType from './dialogs/AlarmDetailByType.vue' |
|
||||
|
|
||||
const detailVisible = ref(false) |
|
||||
const props = defineProps({ |
|
||||
color: { |
|
||||
type: String, |
|
||||
default: 'red', |
|
||||
validator: (val: string) => |
|
||||
['red', 'green', 'yellow', 'blue', 'custom'].includes(val) || |
|
||||
val.startsWith('#') |
|
||||
}, |
|
||||
customColor: { |
|
||||
type: String, |
|
||||
default: '#ff0000' |
|
||||
}, |
|
||||
text: { |
|
||||
type: String, |
|
||||
default: 'ALERT' |
|
||||
}, |
|
||||
// 动画周期(秒) |
|
||||
cycleDuration: { |
|
||||
type: Number, |
|
||||
default: 2 |
|
||||
}, |
|
||||
// 是否激活动画 |
|
||||
active: { |
|
||||
type: Boolean, |
|
||||
default: true |
|
||||
}, |
|
||||
alarmItem: { |
|
||||
type: Object, |
|
||||
default: () => {} |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
const getColor = computed(() => { |
|
||||
const colorMap: Record<string, string> = { |
|
||||
'red': '#ff0000', |
|
||||
'green': '#00cc00', |
|
||||
'yellow': '#ffff00', |
|
||||
'blue': '#0066ff', |
|
||||
'custom': props.customColor |
|
||||
}; |
|
||||
return colorMap[props.color] || props.color; |
|
||||
}); |
|
||||
|
|
||||
const isActive = computed(() => props.active); |
|
||||
|
|
||||
const onShowAlarmDetail = () => { |
|
||||
detailVisible.value = true; |
|
||||
console.log('alarm ==11= ', props.alarmItem) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style scoped> |
|
||||
.alarm-light-container { |
|
||||
display: inline-block; |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
.alarm-light { |
|
||||
width: 7rem; |
|
||||
height: 7rem; |
|
||||
border-radius: 50%; |
|
||||
border: 2px solid rgba(255, 255, 255, 0.5); |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
z-index: 1; |
|
||||
|
|
||||
/* 基础样式 */ |
|
||||
background-color: var(--light-color); |
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); |
|
||||
} |
|
||||
|
|
||||
.light-text { |
|
||||
position: absolute; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
transform: translate(-50%, -50%); |
|
||||
font-size: 14px; |
|
||||
color: white; |
|
||||
font-weight: bold; |
|
||||
text-shadow: 0 0 3px rgba(0, 0, 0, 0.8); |
|
||||
z-index: 2; |
|
||||
} |
|
||||
|
|
||||
/* 从弱到强的脉动动画 */ |
|
||||
.pulse-animation { |
|
||||
animation: pulse 2s infinite ease-in-out; |
|
||||
animation-duration: calc(var(--cycle-duration, 2) * 1s); |
|
||||
} |
|
||||
|
|
||||
@keyframes pulse { |
|
||||
0%, 100% { |
|
||||
box-shadow: |
|
||||
0 0 5px var(--light-color), |
|
||||
0 0 8px var(--light-color), |
|
||||
0 0 10px var(--light-color); |
|
||||
opacity: 0.6; |
|
||||
transform: scale(0.95); |
|
||||
} |
|
||||
50% { |
|
||||
box-shadow: |
|
||||
0 0 10px var(--light-color), |
|
||||
0 0 15px var(--light-color), |
|
||||
0 0 18px var(--light-color), |
|
||||
0 0 20px var(--light-color); |
|
||||
opacity: 1; |
|
||||
transform: scale(1); |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
@ -0,0 +1,67 @@ |
|||||
|
<template> |
||||
|
<div > |
||||
|
<!-- 左边报警列表 --> |
||||
|
<div v-if="alarmList && alarmList.length"> |
||||
|
<el-table |
||||
|
ref="tableRef" |
||||
|
:data="alarmList" |
||||
|
show-overflow-tooltip |
||||
|
header-cell-class-name="table-header" |
||||
|
row-class-name="table-row"> |
||||
|
<el-table-column type="index" label="序号" width="50"></el-table-column> |
||||
|
<el-table-column prop="keyName" label="名称" width="170"> |
||||
|
<template #default="scope"> |
||||
|
{{ scope.row.flagType === 'NormalFlag' ? scope.row.notTriggeredDisName : scope.row.triggeredStateName}} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column prop="flagType" label="类型" width="170"> |
||||
|
<template #default="scope"> |
||||
|
{{ scope.row.flagType === 'NormalFlag' ? '正常' : scope.row.flagType === 'WarningFlag' ? '警告' : '异常'}} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { useDeviceStore } from '@/store' |
||||
|
import type { WarningState } from '@/websocket/socket' |
||||
|
import { ref, watchEffect } from 'vue' |
||||
|
const deviceStore = useDeviceStore() |
||||
|
const alarmList = ref<WarningState[]>([]) |
||||
|
watchEffect(() => { |
||||
|
alarmList.value = deviceStore.alarmList |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.alarm-container { |
||||
|
min-height: 20vh; |
||||
|
text-align: start; |
||||
|
} |
||||
|
.alarm-item { |
||||
|
height: 17vh; |
||||
|
cursor: pointer; |
||||
|
border-radius: 10px; |
||||
|
} |
||||
|
.alarm-item-title{ |
||||
|
font-weight: bold |
||||
|
} |
||||
|
.alarm-name { |
||||
|
flex: 1; |
||||
|
} |
||||
|
.alarm-type { |
||||
|
margin: 0 10px; |
||||
|
padding: 2px 6px; |
||||
|
border-radius: 4px; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.clear-alarm-btn{ |
||||
|
margin-top: 10px; |
||||
|
height: 4rem; |
||||
|
font-size: 20px; |
||||
|
width:7rem; |
||||
|
} |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue