|
|
@ -1,184 +1,88 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<!-- 通信管理弹框 -->
|
|
|
|
<!-- 通信管理弹框 -->
|
|
|
|
<el-dialog
|
|
|
|
<DSDialog title="通信管理" v-model="show" width="1200" class="commManagement-dialog ds-dialog">
|
|
|
|
title="通信管理"
|
|
|
|
<div class="commManagement-container">
|
|
|
|
v-model="dialogVisible"
|
|
|
|
<div class="commManagement-siderBar">
|
|
|
|
width="800px"
|
|
|
|
|
|
|
|
:before-close="handleClose"
|
|
|
|
|
|
|
|
class="custom-dialog"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<!-- 内容容器:左侧菜单 + 右侧表单 -->
|
|
|
|
|
|
|
|
<div class="dialog-container">
|
|
|
|
|
|
|
|
<!-- 左侧导航菜单 -->
|
|
|
|
|
|
|
|
<div class="left-menu">
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
class="menu-item"
|
|
|
|
|
|
|
|
:class="{ active: activeMenu === 'device' }"
|
|
|
|
|
|
|
|
@click="activeMenu = 'device'"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<i class="el-icon-setting"></i> 设备管理
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
class="menu-item"
|
|
|
|
class="commManagement-sidebar-item"
|
|
|
|
:class="{ active: activeMenu === 'receive' }"
|
|
|
|
:class="{ active: activeTab === v.value }"
|
|
|
|
@click="activeMenu = 'receive'"
|
|
|
|
@click="setActiveTab(v)"
|
|
|
|
|
|
|
|
v-for="(v, k) in commBars"
|
|
|
|
|
|
|
|
:key="k"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<i class="el-icon-s-data"></i> 接收事件
|
|
|
|
<!-- // TODO 替换icon -->
|
|
|
|
|
|
|
|
<img :src="activeTab === v.value ? v.iconSelected : v.icon" alt="" class="w-[32px]" />
|
|
|
|
|
|
|
|
<span>{{ v.label }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
|
|
|
|
class="menu-item"
|
|
|
|
|
|
|
|
:class="{ active: activeMenu === 'send' }"
|
|
|
|
|
|
|
|
@click="activeMenu = 'send'"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<i class="el-icon-s-opportunity"></i> 发送事件
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
<div class="commManagement-line-first"></div>
|
|
|
|
class="menu-item"
|
|
|
|
<div class="commManagement-infoList">
|
|
|
|
:class="{ active: activeMenu === 'heartbeat' }"
|
|
|
|
<div class="commManagement-infoList-title">
|
|
|
|
@click="activeMenu = 'heartbeat'"
|
|
|
|
<span>{{ currentTabLabel }}</span>
|
|
|
|
>
|
|
|
|
<div class="infoList-title-btn">+</div>
|
|
|
|
<i class="el-icon-heart-rate"></i> 心跳管理
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="commManagement-infoList-content">
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
class="menu-item"
|
|
|
|
class="commManagement-infoList-item"
|
|
|
|
:class="{ active: activeMenu === 'response' }"
|
|
|
|
:class="{ active: item.enabled }"
|
|
|
|
@click="activeMenu = 'response'"
|
|
|
|
v-for="(item, index) in deviceList"
|
|
|
|
>
|
|
|
|
:key="index"
|
|
|
|
<i class="el-icon-switch-button"></i> 响应配置
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧内容区域 -->
|
|
|
|
|
|
|
|
<div class="right-content">
|
|
|
|
|
|
|
|
<!-- 设备列表 + 协议配置 -->
|
|
|
|
|
|
|
|
<div class="device-section" v-if="activeMenu === 'device'">
|
|
|
|
|
|
|
|
<!-- 设备列表 -->
|
|
|
|
|
|
|
|
<div class="device-list">
|
|
|
|
|
|
|
|
<div class="device-title">设备列表</div>
|
|
|
|
|
|
|
|
<el-button icon="el-icon-plus" size="mini" @click="addDevice"></el-button>
|
|
|
|
|
|
|
|
<div class="device-item" v-for="(item, index) in deviceList" :key="index">
|
|
|
|
|
|
|
|
<span>{{ item.name }}</span>
|
|
|
|
|
|
|
|
<el-switch
|
|
|
|
|
|
|
|
v-model="item.enabled"
|
|
|
|
|
|
|
|
active-text="开启"
|
|
|
|
|
|
|
|
inactive-text="关闭"
|
|
|
|
|
|
|
|
@change="handleSwitch(index)"
|
|
|
|
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
<el-empty :image-size="54" :image="NoDataIcon" style="margin-top: 130px" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="commManagement-line-second"></div>
|
|
|
|
<!-- 通信协议配置 -->
|
|
|
|
<div class="commManagement-content">3</div>
|
|
|
|
<div class="protocol-config">
|
|
|
|
|
|
|
|
<div class="config-title">通信协议</div>
|
|
|
|
|
|
|
|
<el-form label-width="80px">
|
|
|
|
|
|
|
|
<el-form-item label="协议类型">
|
|
|
|
|
|
|
|
<el-select v-model="form.protocolType" placeholder="选择协议">
|
|
|
|
|
|
|
|
<el-option label="TCP客户端" value="tcp"></el-option>
|
|
|
|
|
|
|
|
<el-option label="UDP客户端" value="udp"></el-option>
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="设备名称">
|
|
|
|
|
|
|
|
<el-input v-model="form.deviceName"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="目标IP">
|
|
|
|
|
|
|
|
<el-input v-model="form.targetIp"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="目标端口">
|
|
|
|
|
|
|
|
<el-input v-model="form.targetPort"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="数据上传">
|
|
|
|
|
|
|
|
<el-switch v-model="form.dataUpload"></el-switch>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="自动重连">
|
|
|
|
|
|
|
|
<el-switch v-model="form.autoReconnect"></el-switch>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="接受结束符">
|
|
|
|
|
|
|
|
<el-switch v-model="form.acceptTerminator"></el-switch>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 接收事件 -->
|
|
|
|
|
|
|
|
<div class="event-section" v-else-if="activeMenu === 'receive'">
|
|
|
|
|
|
|
|
<div class="config-title">接收事件</div>
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
|
|
v-model="receiveData"
|
|
|
|
|
|
|
|
placeholder="接收事件内容"
|
|
|
|
|
|
|
|
rows="6"
|
|
|
|
|
|
|
|
class="event-textarea"
|
|
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
|
|
<div class="event-actions">
|
|
|
|
|
|
|
|
<el-checkbox v-model="hexDisplay">16进制显示</el-checkbox>
|
|
|
|
|
|
|
|
<el-button type="primary" size="mini" @click="clearReceive">清空内容</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" size="mini" @click="fetchReceive">接收数据</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 发送事件 -->
|
|
|
|
|
|
|
|
<div class="event-section" v-else-if="activeMenu === 'send'">
|
|
|
|
|
|
|
|
<div class="config-title">发送事件</div>
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
|
|
v-model="sendData"
|
|
|
|
|
|
|
|
placeholder="发送事件内容"
|
|
|
|
|
|
|
|
rows="6"
|
|
|
|
|
|
|
|
class="event-textarea"
|
|
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
|
|
<div class="event-actions">
|
|
|
|
|
|
|
|
<el-button type="primary" size="mini" @click="sendDataAction">发送数据</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</DSDialog>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 心跳管理 -->
|
|
|
|
|
|
|
|
<div class="heartbeat-section" v-else-if="activeMenu === 'heartbeat'">
|
|
|
|
|
|
|
|
<div class="config-title">心跳管理</div>
|
|
|
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
|
|
|
<el-form-item label="心跳间隔">
|
|
|
|
|
|
|
|
<el-input v-model="heartbeatInterval" placeholder="单位:秒"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="心跳内容">
|
|
|
|
|
|
|
|
<el-input v-model="heartbeatContent"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 响应配置 -->
|
|
|
|
|
|
|
|
<div class="response-section" v-else-if="activeMenu === 'response'">
|
|
|
|
|
|
|
|
<div class="config-title">响应配置</div>
|
|
|
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
|
|
|
<el-form-item label="响应超时">
|
|
|
|
|
|
|
|
<el-input v-model="responseTimeout" placeholder="单位:秒"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="重试次数">
|
|
|
|
|
|
|
|
<el-input v-model="retryCount"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部操作按钮 -->
|
|
|
|
|
|
|
|
<div class="bottom-actions">
|
|
|
|
|
|
|
|
<el-button type="danger" @click="deleteDevice">删除设备</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 触发弹框按钮(用于测试) -->
|
|
|
|
|
|
|
|
<el-button type="primary" @click="dialogVisible = true" style="margin: 20px"
|
|
|
|
|
|
|
|
>打开通信管理</el-button
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { ref, reactive } from 'vue'
|
|
|
|
import { DSButton } from '@/components/Button'
|
|
|
|
|
|
|
|
import { DSDialog } from '@/components/Dialog'
|
|
|
|
|
|
|
|
import DeviceIcon from '@/assets/images/common/device.png'
|
|
|
|
|
|
|
|
import DeviceSelectedIcon from '@/assets/images/common/device_selected.png'
|
|
|
|
|
|
|
|
import SendIcon from '@/assets/images/common/send.png'
|
|
|
|
|
|
|
|
import SendSelectedIcon from '@/assets/images/common/send_selected.png'
|
|
|
|
|
|
|
|
import ReceiveIcon from '@/assets/images/common/receive.png'
|
|
|
|
|
|
|
|
import ReceiveSelectedIcon from '@/assets/images/common/receive_selected.png'
|
|
|
|
|
|
|
|
import HeartbeatIcon from '@/assets/images/common/heartbeat.png'
|
|
|
|
|
|
|
|
import HeartbeatSelectedIcon from '@/assets/images/common/heartbeat_selected.png'
|
|
|
|
|
|
|
|
import ResponseIcon from '@/assets/images/common/response.png'
|
|
|
|
|
|
|
|
import ResponseSelectedIcon from '@/assets/images/common/response_selected.png'
|
|
|
|
|
|
|
|
import NoDataIcon from '@/assets/images/common/no_data.png'
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
|
|
/** 弹窗显隐 */
|
|
|
|
|
|
|
|
value: boolean
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Emits {
|
|
|
|
|
|
|
|
(e: 'update:value', val: boolean): void
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
|
|
|
|
|
|
value: false
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const emit = defineEmits<Emits>()
|
|
|
|
|
|
|
|
|
|
|
|
// 弹框显示状态
|
|
|
|
// 弹框显示状态
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
|
|
|
|
const show = computed({
|
|
|
|
|
|
|
|
get() {
|
|
|
|
|
|
|
|
return props.value
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
set(val: boolean) {
|
|
|
|
|
|
|
|
emit('update:value', val)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
// 左侧菜单激活状态
|
|
|
|
// 左侧菜单激活状态
|
|
|
|
const activeMenu = ref('device') // device/receive/send/heartbeat/response
|
|
|
|
const activeTab = ref('device') // device/receive/send/heartbeat/response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据 activeTab 匹配对应的中文 label
|
|
|
|
|
|
|
|
const currentTabLabel = computed(() => {
|
|
|
|
|
|
|
|
// 在 commBars 中找到 value 与 activeTab 匹配的项,返回其 label
|
|
|
|
|
|
|
|
const matched = commBars.find((item) => item.value === activeTab.value)
|
|
|
|
|
|
|
|
// 如果找不到匹配项,默认显示空或提示文字
|
|
|
|
|
|
|
|
return matched ? matched.label : ''
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 设备列表
|
|
|
|
// 设备列表
|
|
|
|
const deviceList = reactive([
|
|
|
|
const deviceList = reactive([
|
|
|
@ -186,6 +90,29 @@ const deviceList = reactive([
|
|
|
|
{ name: '2.UDP客户端', enabled: false }
|
|
|
|
{ name: '2.UDP客户端', enabled: false }
|
|
|
|
])
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface CommBar {
|
|
|
|
|
|
|
|
label: string
|
|
|
|
|
|
|
|
value: 'device' | 'receive' | 'send' | 'heartbeat' | 'response'
|
|
|
|
|
|
|
|
icon: string
|
|
|
|
|
|
|
|
iconSelected: string
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const commBars: CommBar[] = [
|
|
|
|
|
|
|
|
{ label: '设备列表', value: 'device', icon: DeviceIcon, iconSelected: DeviceSelectedIcon },
|
|
|
|
|
|
|
|
{ label: '接收事件', value: 'receive', icon: ReceiveIcon, iconSelected: ReceiveSelectedIcon },
|
|
|
|
|
|
|
|
{ label: '发送事件', value: 'send', icon: SendIcon, iconSelected: SendSelectedIcon },
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
label: '心跳管理',
|
|
|
|
|
|
|
|
value: 'heartbeat',
|
|
|
|
|
|
|
|
icon: HeartbeatIcon,
|
|
|
|
|
|
|
|
iconSelected: HeartbeatSelectedIcon
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{ label: '响应配置', value: 'response', icon: ResponseIcon, iconSelected: ResponseSelectedIcon }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
const setActiveTab = (tab: SettingItem) => {
|
|
|
|
|
|
|
|
activeTab.value = tab.value
|
|
|
|
|
|
|
|
console.log(activeTab.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
// 表单数据
|
|
|
|
const form = reactive({
|
|
|
|
const form = reactive({
|
|
|
|
protocolType: 'tcp', // tcp/udp
|
|
|
|
protocolType: 'tcp', // tcp/udp
|
|
|
@ -203,222 +130,74 @@ const receiveData = ref('')
|
|
|
|
const sendData = ref('')
|
|
|
|
const sendData = ref('')
|
|
|
|
// 16进制显示
|
|
|
|
// 16进制显示
|
|
|
|
const hexDisplay = ref(true)
|
|
|
|
const hexDisplay = ref(true)
|
|
|
|
|
|
|
|
|
|
|
|
// 心跳管理
|
|
|
|
|
|
|
|
const heartbeatInterval = ref('')
|
|
|
|
|
|
|
|
const heartbeatContent = ref('')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 响应配置
|
|
|
|
|
|
|
|
const responseTimeout = ref('')
|
|
|
|
|
|
|
|
const retryCount = ref('')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加设备
|
|
|
|
|
|
|
|
const addDevice = () => {
|
|
|
|
|
|
|
|
deviceList.push({ name: `新设备${deviceList.length + 1}`, enabled: false })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 开关切换
|
|
|
|
|
|
|
|
const handleSwitch = (index: number) => {
|
|
|
|
|
|
|
|
console.log(`设备 ${deviceList[index].name} 状态:`, deviceList[index].enabled)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清空接收内容
|
|
|
|
|
|
|
|
const clearReceive = () => {
|
|
|
|
|
|
|
|
receiveData.value = ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 接收数据
|
|
|
|
|
|
|
|
const fetchReceive = () => {
|
|
|
|
|
|
|
|
receiveData.value = '模拟接收数据:0A 0B 0C 0D' // 实际对接接口
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送数据
|
|
|
|
|
|
|
|
const sendDataAction = () => {
|
|
|
|
|
|
|
|
console.log('发送数据:', sendData.value)
|
|
|
|
|
|
|
|
// 实际对接接口发送数据
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 删除设备
|
|
|
|
|
|
|
|
const deleteDevice = () => {
|
|
|
|
|
|
|
|
if (deviceList.length > 0) {
|
|
|
|
|
|
|
|
deviceList.pop()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭弹框回调
|
|
|
|
|
|
|
|
const handleClose = (done: () => void) => {
|
|
|
|
|
|
|
|
// 重置表单
|
|
|
|
|
|
|
|
form.protocolType = 'tcp'
|
|
|
|
|
|
|
|
form.deviceName = 'TCP客户端'
|
|
|
|
|
|
|
|
form.targetIp = ''
|
|
|
|
|
|
|
|
form.targetPort = ''
|
|
|
|
|
|
|
|
form.dataUpload = false
|
|
|
|
|
|
|
|
form.autoReconnect = false
|
|
|
|
|
|
|
|
form.acceptTerminator = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 重置事件内容
|
|
|
|
|
|
|
|
receiveData.value = ''
|
|
|
|
|
|
|
|
sendData.value = ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
done()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
<style scoped lang="scss">
|
|
|
|
/* 弹框整体样式 */
|
|
|
|
/* 弹框整体样式 */
|
|
|
|
.custom-dialog {
|
|
|
|
.commManagement-container {
|
|
|
|
.el-dialog__header {
|
|
|
|
position: relative;
|
|
|
|
border-bottom: 1px solid #444;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
height: 766px;
|
|
|
|
.el-dialog__body {
|
|
|
|
box-sizing: border-box;
|
|
|
|
padding: 0;
|
|
|
|
|
|
|
|
background: #2c2c2c;
|
|
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 内容容器:左侧菜单 + 右侧表单 */
|
|
|
|
|
|
|
|
.dialog-container {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
height: 500px;
|
|
|
|
.commManagement-siderBar {
|
|
|
|
padding: 20px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
}
|
|
|
|
width: 120px;
|
|
|
|
|
|
|
|
height: 100%;
|
|
|
|
/* 左侧菜单 */
|
|
|
|
padding: 24px;
|
|
|
|
.left-menu {
|
|
|
|
|
|
|
|
width: 180px;
|
|
|
|
|
|
|
|
background: #373737;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
padding: 20px 0;
|
|
|
|
|
|
|
|
margin-right: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.menu-item {
|
|
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
transition: background 0.3s;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8px;
|
|
|
|
.commManagement-sidebar-item {
|
|
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
&:hover {
|
|
|
|
height: 62px;
|
|
|
|
background: #4d4d4d;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
|
|
background: #4d4d4d;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 右侧内容区域 */
|
|
|
|
|
|
|
|
.right-content {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 设备管理区域 */
|
|
|
|
|
|
|
|
.device-section {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-list {
|
|
|
|
|
|
|
|
width: 220px;
|
|
|
|
|
|
|
|
background: #373737;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-title {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.commManagement-infoList {
|
|
|
|
.device-item {
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
width: 252px;
|
|
|
|
|
|
|
|
.commManagement-infoList-title {
|
|
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: 8px;
|
|
|
|
justify-content: space-between;
|
|
|
|
}
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
height: 50px;
|
|
|
|
|
|
|
|
padding: 0 16px;
|
|
|
|
.protocol-config {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
background: #373737;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.config-title {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 事件区域(接收/发送) */
|
|
|
|
|
|
|
|
.event-section {
|
|
|
|
|
|
|
|
background: #373737;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.config-title {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
font-size: 14px;
|
|
|
|
font-weight: bold;
|
|
|
|
font-weight: bold;
|
|
|
|
margin-bottom: 12px;
|
|
|
|
.infoList-title-btn {
|
|
|
|
}
|
|
|
|
width: 24px;
|
|
|
|
|
|
|
|
height: 24px;
|
|
|
|
.event-textarea {
|
|
|
|
background: #154ddd;
|
|
|
|
width: 100%;
|
|
|
|
border: none;
|
|
|
|
background: #2c2c2c;
|
|
|
|
|
|
|
|
color: #fff;
|
|
|
|
color: #fff;
|
|
|
|
border: 1px solid #444;
|
|
|
|
font-size: 24px;
|
|
|
|
border-radius: 4px;
|
|
|
|
text-align: center;
|
|
|
|
padding: 8px;
|
|
|
|
line-height: 20px;
|
|
|
|
resize: none;
|
|
|
|
border-radius: 50%;
|
|
|
|
}
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
|
|
.event-actions {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 心跳管理区域 */
|
|
|
|
|
|
|
|
.heartbeat-section {
|
|
|
|
|
|
|
|
background: #373737;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.config-title {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.commManagement-content {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.commManagement-line-first,
|
|
|
|
/* 响应配置区域 */
|
|
|
|
.commManagement-line-second {
|
|
|
|
.response-section {
|
|
|
|
position: absolute;
|
|
|
|
background: #373737;
|
|
|
|
left: 120px;
|
|
|
|
border-radius: 4px;
|
|
|
|
width: 1px;
|
|
|
|
padding: 16px;
|
|
|
|
height: 100vh;
|
|
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
.config-title {
|
|
|
|
opacity: 0.3;
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.commManagement-line-second {
|
|
|
|
|
|
|
|
left: 372px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 底部操作按钮 */
|
|
|
|
|
|
|
|
.bottom-actions {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|