feat: 设备管理

master
JINGYJ 3 weeks ago
parent b6a613a9be
commit c08cd90384

@ -0,0 +1,361 @@
<template>
<!-- 通信管理弹框 -->
<DSDialog title="通信管理" v-model="show" width="1200" class="commManagement-dialog ds-dialog">
<div class="commManagement-container">
<div class="commManagement-siderBar">
<div
class="commManagement-sidebar-item"
:class="{ active: activeTab === v.value }"
@click="setActiveTab(v)"
v-for="(v, k) in commBars"
:key="k"
>
<!-- // TODO icon -->
<img :src="activeTab === v.value ? v.iconSelected : v.icon" alt="" class="w-[32px]" />
<span>{{ v.label }}</span>
</div>
</div>
<div class="commManagement-line-first" />
<div class="commManagement-infoList">
<div class="commManagement-infoList-title">
<span>{{ currentTabLabel }}</span>
<div class="infoList-title-btn" @click="addDevice">+</div>
</div>
<div class="commManagement-infoList-content">
<div
class="commManagement-infoList-item"
:class="{ active: deviceTab === item.name }"
v-for="(item, index) in deviceList"
:key="index"
@click="selectDevice(item)"
>
<span>{{ item.name }}</span>
<el-switch v-model="item.enabled" size="small" />
</div>
<el-empty
:image-size="54"
:image="NoDataIcon"
style="margin-top: 130px"
v-if="deviceList.length === 0"
/>
</div>
</div>
<div class="commManagement-line-second" />
<div class="commManagement-content">
<el-form label-width="auto" size="default" :model="formInfoDevice" style="max-width: 752px">
<div>通信协议</div>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="协议类型" label-position="top">
<el-input v-model="formDeviceInfo.protocol" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" label-position="top">
<el-input v-model="formDeviceInfo.deviceName" />
</el-form-item>
</el-col>
</el-row>
<div>通信参数</div>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="目标IP" label-position="top">
<el-input v-model="formDeviceInfo.IP" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="目标端口" label-position="top">
<el-input v-model="formDeviceInfo.targetPort" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="数据上传" label-position="left">
<el-switch v-model="formDeviceInfo.dataUpload" />
</el-form-item>
<el-form-item label="自动重连" label-position="left">
<el-switch v-model="formDeviceInfo.reconnect" />
</el-form-item>
<el-form-item label="接受结束符" label-position="left">
<el-switch v-model="formDeviceInfo.acceptEnd" />
</el-form-item>
<el-form-item v-if="formDeviceInfo.acceptEnd">
<el-tabs v-model="dataTab" class="data-tabs" @tab-click="handleClick">
<el-tab-pane label="接收数据" name="receive">
<el-input
v-model="formDeviceInfo.endInfo"
type="textarea"
resize="none"
class="fixed-height-textarea"
:rows="4"
maxlength="350"
/>
</el-tab-pane>
<el-tab-pane label="发送数据" name="send">
<el-input
v-model="formDeviceInfo.endInfo"
type="textarea"
resize="none"
class="fixed-height-textarea"
:rows="4"
maxlength="350"
/>
</el-tab-pane>
</el-tabs>
</el-form-item>
<el-row :gutter="20">
<el-col :span="6">
<el-checkbox value="16radix" name="type"> 16进制 </el-checkbox>
</el-col>
<el-col :span="6" :offset="12">
<DSButton type="danger" class="mr-2 form-device-btn">清空内容</DSButton>
<DSButton type="danger" class="form-device-btn"> 接收数据</DSButton>
</el-col>
</el-row>
</el-form>
</div>
</div>
</DSDialog>
<DeviceDialog v-model:value="isDeviceDialog" />
</template>
<script setup lang="ts">
defineOptions({
name: 'CommManagement'
})
import { DSButton } from '@/components/Button'
import { DSDialog } from '@/components/Dialog'
import DeviceDialog from './deviceDialog.vue'
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 {
/** import DeviceDialog from './deviceDialog.vue';
弹窗显隐 */
value: boolean
}
interface Emits {
(e: 'update:value', val: boolean): void
}
const props = withDefaults(defineProps<Props>(), {
value: false
})
const emit = defineEmits<Emits>()
const show = computed({
get() {
return props.value
},
set(val: boolean) {
emit('update:value', val)
}
})
const isDeviceDialog = ref(false)
//
const activeTab = ref('device') // device/receive/send/heartbeat/response
const deviceTab = ref('') // 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([
{
name: '1.TCP客户端',
enabled: false,
info: {
protocol: '1',
deviceName: '1',
IP: '1',
targetPort: '1',
dataUpload: false,
reconnect: false,
acceptEnd: false,
endInfo: '1'
}
},
{ name: '2.UDP客户端', enabled: false }
])
const dataTab = ref('receive')
const formDeviceInfo = reactive({
protocol: '',
deviceName: '',
IP: '',
targetPort: '',
dataUpload: false,
reconnect: false,
acceptEnd: false,
endInfo: ''
})
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 selectDevice = (device: Device) => {
deviceTab.value = device.name
Object.assign(formDeviceInfo, device.info)
}
//
const addDevice = () => {
if (isDeviceDialog.value) {
isDeviceDialog.value = false
} else {
//
isDeviceDialog.value = true
}
console.log(isDeviceDialog.value, 'isDeviceDialog.value')
}
//
const receiveData = ref('')
//
const sendData = ref('')
// 16
const hexDisplay = ref(true)
</script>
<style scoped lang="scss">
/* 弹框整体样式 */
.commManagement-container {
position: relative;
width: 100%;
height: 766px;
box-sizing: border-box;
display: flex;
.commManagement-siderBar {
box-sizing: border-box;
width: 120px;
height: 100%;
padding: 24px;
display: flex;
flex-direction: column;
align-items: center;
.commManagement-sidebar-item {
margin-bottom: 16px;
height: 62px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
}
.commManagement-infoList {
box-sizing: border-box;
width: 252px;
.commManagement-infoList-title {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 50px;
padding: 0 16px;
font-size: 14px;
font-weight: bold;
.infoList-title-btn {
width: 24px;
height: 24px;
background: #154ddd;
border: none;
color: #fff;
font-size: 24px;
text-align: center;
line-height: 20px;
border-radius: 50%;
cursor: pointer;
}
}
.commManagement-infoList-content {
.commManagement-infoList-item {
box-sizing: border-box;
width: 100%;
height: 32px;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.commManagement-infoList-item.active {
background: #f2f2f7;
span {
color: #154ddd;
}
}
}
}
.commManagement-content {
flex: 1;
box-sizing: border-box;
padding: 16px 24px 24px;
.data-tabs {
width: 100%;
:deep(.el-tabs__item) {
color: #fff;
}
:deep(.fixed-height-textarea) {
margin-bottom: 8px;
height: 110px !important;
min-height: 110px !important;
max-height: 110px !important;
.el-textarea__inner {
height: 110px !important;
background: #303136;
color: #fff;
}
}
}
.form-device-btn {
width: 80px;
padding: 0 12px;
}
}
.commManagement-line-first,
.commManagement-line-second {
position: absolute;
left: 120px;
width: 1px;
height: 100vh;
background-color: #fff;
opacity: 0.3;
}
.commManagement-line-second {
left: 372px;
}
}
</style>

@ -0,0 +1,136 @@
<template>
<!-- 设备管理弹框 -->
<el-dialog
title="设备管理"
v-model="show"
width="800"
class="deviceManagement-dialog ds-dialog"
style="margin-top: 244px"
>
<div class="deviceManagement-container">
<!-- 弹窗内容 -->
<el-form label-width="auto" size="default" :model="formDeviceInfo" style="max-width: 752px">
<div>通信协议</div>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="协议类型" label-position="top">
<el-input v-model="formDeviceInfo.protocol" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" label-position="top">
<el-input v-model="formDeviceInfo.deviceName" />
</el-form-item>
</el-col>
</el-row>
<div>通信参数</div>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="目标IP" label-position="top">
<el-input v-model="formDeviceInfo.IP" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="目标端口" label-position="top">
<el-input v-model="formDeviceInfo.targetPort" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="数据上传" label-position="left">
<el-switch v-model="formDeviceInfo.dataUpload" />
</el-form-item>
<el-form-item label="自动重连" label-position="left">
<el-switch v-model="formDeviceInfo.reconnect" />
</el-form-item>
<el-form-item label="接受结束符" label-position="left">
<el-switch v-model="formDeviceInfo.acceptEnd" />
</el-form-item>
<el-form-item v-if="formDeviceInfo.acceptEnd">
<el-input
v-model="formDeviceInfo.endInfo"
type="textarea"
resize="none"
class="fixed-height-textarea"
:rows="4"
maxlength="350"
/>
<el-button style="background: #454851; color: #fff; width: 66px" size="small"
>\r</el-button
>
<el-button style="background: #454851; color: #fff; width: 66px" size="small"
>\n</el-button
>
<el-button style="background: #454851; color: #fff; width: 66px" size="small"
>\r\n</el-button
>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer mr-[24px] pb-[24px] pt-[16px] flex justify-end">
<DSButton type="primary" class="">创建</DSButton>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { DSButton } from '@/components/Button'
// v-model:value props.value
interface Props {
value: boolean
}
interface Emits {
(e: 'update:value', val: boolean): void
}
const props = withDefaults(defineProps<Props>(), {
value: false
})
const emit = defineEmits<Emits>()
watch(
() => props.value,
(newVal, oldVal) => {
console.log('props.value 变化:', '旧值:', oldVal, '新值:', newVal)
}
)
//
const show = computed({
get() {
return props.value // isDeviceDialog
},
set(val) {
emit('update:value', val) //
}
})
const formDeviceInfo = reactive({
protocol: '',
deviceName: '',
IP: '',
targetPort: '',
dataUpload: false,
reconnect: false,
acceptEnd: false,
endInfo: ''
})
</script>
<style scoped lang="scss">
.deviceManagement-container {
box-sizing: border-box;
width: 100%;
height: 564px;
padding: 16px 24px 24px;
:deep(.fixed-height-textarea) {
margin-bottom: 8px;
height: 110px !important;
min-height: 110px !important;
max-height: 110px !important;
.el-textarea__inner {
height: 110px !important;
background: #303136;
}
}
}
</style>

@ -1,203 +0,0 @@
<template>
<!-- 通信管理弹框 -->
<DSDialog title="通信管理" v-model="show" width="1200" class="commManagement-dialog ds-dialog">
<div class="commManagement-container">
<div class="commManagement-siderBar">
<div
class="commManagement-sidebar-item"
:class="{ active: activeTab === v.value }"
@click="setActiveTab(v)"
v-for="(v, k) in commBars"
:key="k"
>
<!-- // TODO icon -->
<img :src="activeTab === v.value ? v.iconSelected : v.icon" alt="" class="w-[32px]" />
<span>{{ v.label }}</span>
</div>
</div>
<div class="commManagement-line-first"></div>
<div class="commManagement-infoList">
<div class="commManagement-infoList-title">
<span>{{ currentTabLabel }}</span>
<div class="infoList-title-btn">+</div>
</div>
<div class="commManagement-infoList-content">
<div
class="commManagement-infoList-item"
:class="{ active: item.enabled }"
v-for="(item, index) in deviceList"
:key="index"
/>
<el-empty :image-size="54" :image="NoDataIcon" style="margin-top: 130px" />
</div>
</div>
<div class="commManagement-line-second"></div>
<div class="commManagement-content">3</div>
</div>
</DSDialog>
</template>
<script setup lang="ts">
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 show = computed({
get() {
return props.value
},
set(val: boolean) {
emit('update:value', val)
}
})
//
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([
{ name: '1.TCP客户端', enabled: true },
{ 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({
protocolType: 'tcp', // tcp/udp
deviceName: 'TCP客户端',
targetIp: '',
targetPort: '',
dataUpload: false,
autoReconnect: false,
acceptTerminator: true
})
//
const receiveData = ref('')
//
const sendData = ref('')
// 16
const hexDisplay = ref(true)
</script>
<style scoped lang="scss">
/* 弹框整体样式 */
.commManagement-container {
position: relative;
width: 100%;
height: 766px;
box-sizing: border-box;
display: flex;
.commManagement-siderBar {
box-sizing: border-box;
width: 120px;
height: 100%;
padding: 24px;
display: flex;
flex-direction: column;
align-items: center;
.commManagement-sidebar-item {
margin-bottom: 16px;
height: 62px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
}
.commManagement-infoList {
box-sizing: border-box;
width: 252px;
.commManagement-infoList-title {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 50px;
padding: 0 16px;
font-size: 14px;
font-weight: bold;
.infoList-title-btn {
width: 24px;
height: 24px;
background: #154ddd;
border: none;
color: #fff;
font-size: 24px;
text-align: center;
line-height: 20px;
border-radius: 50%;
cursor: pointer;
}
}
}
.commManagement-content {
flex: 1;
}
.commManagement-line-first,
.commManagement-line-second {
position: absolute;
left: 120px;
width: 1px;
height: 100vh;
background-color: #fff;
opacity: 0.3;
}
.commManagement-line-second {
left: 372px;
}
}
</style>

@ -44,7 +44,7 @@ import OutputView from './Workflow/outputView.vue'
import ResultsView from './Workflow/resultsView.vue' import ResultsView from './Workflow/resultsView.vue'
import SettingList from './Settings/settingList.vue' import SettingList from './Settings/settingList.vue'
import LogList from './LogManagement/logList.vue' import LogList from './LogManagement/logList.vue'
import CommManagement from './CommManagement/index.vue' import CommManagement from './CommManagement/commManagement.vue'
const isOpenSetting = ref<boolean>(false) // const isOpenSetting = ref<boolean>(false) //
const isOpenLog = ref<boolean>(false) // const isOpenLog = ref<boolean>(false) //
const isOpenCommManagement = ref<boolean>(false) // const isOpenCommManagement = ref<boolean>(false) //

Loading…
Cancel
Save