Files
admin-govern/src/views/govern/device/control/moduleData.vue
2025-07-08 10:47:04 +08:00

316 lines
10 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>
<!-- 运行 运行(中断) 运行(故障) 离线 -->
<div :style="height" style="overflow-y: auto" v-loading="loading">
<div class="container">
<div class="tabs-container">
<!-- 左侧标签头 -->
<div class="tab-list" :style="echartHeight" style="overflow-y: auto">
<button
v-for="(item, index) in list"
:key="index"
:class="{ 'tab-button active': activeTab === index, 'tab-button': activeTab !== index }"
@click="changeTab(index)"
>
<span>{{ item.moduleName }}</span>
<el-tag
class="ml10"
:type="item.moduleState == '离线' ? 'danger' : 'success'"
size="small"
effect="dark"
>
{{ item.moduleState }}
</el-tag>
</button>
</div>
<!-- 右侧内容区域 -->
<div class="tab-content-container flex-1" :key="activeTab">
<div :style="echartHeight">
<MyEchart :options="echartList.options" v-if="echartList.dataList != null" />
<el-empty description="暂无数据" style="width: 100%; height: 100%" v-else></el-empty>
</div>
</div>
</div>
</div>
<!-- <el-collapse v-model="activeNames" v-loading="loading">
<el-collapse-item v-for="(item, index) in list" :key="index" :name="index">
<template #title>
<div class="header">
{{ item.moduleName }}
<el-tag
class="ml10"
:type="item.moduleState == '离线' ? 'danger' : 'success'"
size="small"
effect="dark"
>
{{ item.moduleState }}
</el-tag>
</div>
</template>
<div :style="echartHeight" style="min-height: 150px">
<MyEchart :options="item.options" v-if="item.dataList != null" />
<el-empty description="暂无数据" style="height: 130px" v-else></el-empty>
</div>
</el-collapse-item>
</el-collapse> -->
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { mainHeight } from '@/utils/layout'
import { WarnTriangleFilled } from '@element-plus/icons-vue'
import { getModuleState } from '@/api/cs-device-boot/EquipmentDelivery'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { ElMessage } from 'element-plus'
import { chain } from 'lodash'
const list: any = ref([])
const loading = ref(false)
const height = ref(mainHeight(290))
const echartHeight = ref(mainHeight(302))
const activeTab = ref(0)
const echartList: any = ref({})
const setData = (data: any) => {
activeTab.value = 0
// echartHeight.value = mainHeight(292 + data.length * 49, data.length)
data.forEach((item: any) => {
// console.log('🚀 ~ setData ~ data:', data)
if (item.dataList == null) return
item.options = {
title: {
show: false
},
tooltip: {
formatter: function (params: any) {
var tips = params[0].data[0] + '' + params[0].data[2] + '<br/>'
if (params[0].data[3] == 1) {
tips += '事件:' + params[0].data[4]
}
return tips
}
},
xAxis: {
type: 'time',
name: '时间',
//
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
// 添加自定义图例
legend: {
show: true,
type: 'plain',
top: 0,
itemWidth: 14, // 图例标记宽度
itemHeight: 14, // 图例标记高度
data: [
{
name: '事件',
icon: 'path://M0,10 L10,10 L5,0 Z', // 自定义三角形路径
textStyle: {
color: '#333',
fontSize: 12
}
}
],
itemStyle: {
color: '#FFB74D' // 图例标记颜色与数据标记一致
}
},
toolbox: {
show: false
},
grid: {
top: '30px'
},
yAxis: {
max: 1,
data: ['运行', '中断'],
interval: 1,
axisLabel: {
formatter: value => {
// if (value === 0) {
// return ` `
// }
if (value === 0) {
return `{lx|离线} `
}
if (value === 1) {
return `{yx|运行} `
}
},
rich: {
yx: {
backgroundColor: '#67c23a',
color: '#fff',
borderRadius: 5,
padding: [1, 3],
fontWeight: 600,
fontSize: 12,
align: 'center',
textAlign: 'center',
width: 35,
height: 20,
borderColor: '#000'
},
lx: {
backgroundColor: '#f56c6c',
color: '#fff',
borderRadius: 5,
padding: [1, 3],
fontWeight: 600,
fontSize: 12,
align: 'center',
textAlign: 'center',
width: 35,
height: 20,
borderColor: '#000'
}
}
}
},
options: {
series: [
{
name: '事件',
type: 'line',
data: item.dataList.map((k: any) => [
k.time,
k.stateDesc == '离线' ? 0 : 1,
k.stateDesc,
k.dataType,
k.eventName
]),
step: 'end',
symbol: 'none',
// 动态显示标记
markPoint: {
symbol: 'triangle', // 使用三角形标记
symbolSize: 10, // 标记大小
symbolOffset: [0, 6], // 向上偏移,放置在线条上方
data: item.dataList
.filter((k: any) => k.dataType === 1)
.map((k: any) => ({
name: k.stateDesc,
coord: [k.time, k.stateDesc === '离线' ? 0 : 1],
itemStyle: {
color: '#FFB74D', // 亮黄色填充
borderColor: '#FFB74D', // 边框颜色
borderWidth: 1 // 边框宽度
}
}))
}
}
]
}
}
})
list.value = data
echartList.value = list.value[activeTab.value]
}
const getModule = async (id: string) => {
loading.value = true
await getModuleState({ id: id }).then(res => {
res.data.forEach((item: any) => {
list.value.forEach((k: any) => {
if (k.moduleName === item.moduleName) {
k.moduleState = item.moduleState
}
})
})
ElMessage.success('刷新成功')
})
loading.value = false
}
const changeTab = (e: any) => {
echartList.value = list.value[e]
activeTab.value = e
}
defineExpose({ setData, getModule })
</script>
<style lang="scss" scoped>
.container {
margin: 10px 10px 0 10px;
background-color: white;
border-radius: 0.5rem;
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.tabs-container {
display: flex;
flex-direction: column;
height: 100%;
}
@media (min-width: 768px) {
.tabs-container {
flex-direction: row;
}
}
.tab-list {
width: 100%;
border-bottom: 1px solid #e2e8f0;
background-color: #f8fafc;
}
@media (min-width: 768px) {
.tab-list {
width: 140px;
border-right: 1px solid #e2e8f0;
border-bottom: none;
}
}
.tab-button {
display: flex;
align-items: center;
width: 100%;
padding: 15px 20px;
text-align: left;
border: none;
background: none;
cursor: pointer;
font-size: 14px;
color: #64748b;
border-right: 4px solid transparent;
transition: all 0.2s ease;
}
.tab-button:hover {
background-color: #f1f5f9;
color: #475569;
}
.tab-button.active {
background-color: #e2e8f0;
color: #000;
border-right-color: var(--el-color-primary);
font-weight: 700;
}
.tab-button i {
width: 1.25rem;
margin-right: 0.75rem;
}
.tab-content-container {
flex: 1;
}
</style>