链路:链路参数添加配置项

This commit is contained in:
高云鹏 2024-07-15 14:19:32 +08:00
parent 1342e205d5
commit fcea8f3227
4 changed files with 995 additions and 25 deletions

View File

@ -31,7 +31,9 @@
import { ref } from 'vue'
import { ElContainer, ElAside, ElHeader, ElMain } from 'element-plus'
const props = defineProps<{ hasAside: boolean }>()
const props = withDefaults(defineProps<{ hasAside: boolean }>(), {
hasAside: false,
})
</script>
<style lang="scss" scoped>

View File

@ -1,6 +1,6 @@
<template>
<div class="node">
<el-dialog v-model="nodeVisible" :title="nodeTitle" width="600">
<el-dialog v-model="nodeVisible" :title="nodeTitle" width="600" @close="closeNodeForm">
<el-form :model="nodeForm" ref="nodeFormRef" :label-width="100" :rules="nodeFormRules">
<el-form-item prop="nodeName" :label="nodeKeyEnum['nodeName']">
<el-input v-model="nodeForm.nodeName" :disabled="nodeFormDisabled" :placeholder="'请输入' + nodeKeyEnum['nodeName']"></el-input>
@ -24,25 +24,19 @@
<el-button @click="closeNodeForm">关闭</el-button>
</template>
</el-dialog>
<el-dialog v-model="linkVisible" :title="linkTitle" width="600">
<el-dialog v-model="linkVisible" :title="linkTitle" width="600" @close="closeLinkForm">
<el-form :model="linkForm" ref="linkFormRef" :label-width="100" :rules="linkFormRules">
<el-form-item prop="linkName" :label="linkKeyEnum['linkName']">
<el-input v-model="linkForm.linkName" :placeholder="'请输入' + linkKeyEnum['linkName']"></el-input>
</el-form-item>
<el-form-item prop="protocol" :label="linkKeyEnum['protocol']">
<el-input v-model="linkForm.protocol" :placeholder="'请输入' + linkKeyEnum['protocol']"></el-input>
<el-select v-model="linkForm.protocol" :placeholder="'请选择' + linkKeyEnum['protocol']">
<el-option v-for="item in protocolList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="params" :label="linkKeyEnum['params']">
<el-input v-model="linkForm.params" :placeholder="'请输入' + linkKeyEnum['params']"></el-input>
</el-form-item>
<el-form-item prop="nodeId" :label="linkKeyEnum['nodeName']">
<!-- <el-input v-model="linkForm.nodeId" :placeholder="'请输入' + linkKeyEnum['nodeName']"></el-input> -->
<el-tree-select
:data="treeData"
v-model="linkForm.nodeId"
:placeholder="'请选择' + linkKeyEnum['nodeName']"
:props="{ label: 'nodeName', value: 'id' }"
></el-tree-select>
<!-- <el-input v-model="linkForm.params" :placeholder="'请输入' + linkKeyEnum['params']"></el-input> -->
<el-button @click="openProtocolPart">协议参数</el-button>
</el-form-item>
</el-form>
<template #footer>
@ -87,11 +81,15 @@
</div>
</template>
<template #mainMain>
<el-table :data="linkTableData" class="tablePart">
<el-table :data="linkTableData" class="tablePart" highlight-current-row>
<el-table-column prop="linkName" label="链路名称" align="center"></el-table-column>
<el-table-column prop="protocol" label="协议类型" align="center"></el-table-column>
<el-table-column prop="params" label="参数" align="center"></el-table-column>
<el-table-column prop="nodeName" label="节点名称" align="center"></el-table-column>
<el-table-column prop="protocolName" label="协议类型" align="center"></el-table-column>
<el-table-column prop="params" label="参数" align="center">
<template #default="scoped">
<el-button @click="openParams(scoped.row)">查看参数</el-button>
</template>
</el-table-column>
<!-- <el-table-column prop="nodeName" label="节点名称" align="center"></el-table-column> -->
<el-table-column fixed="right" label="操作" min-width="80" align="center">
<template #default="scope">
<div class="tableOperate">
@ -123,7 +121,7 @@
<template #default>
<div class="modelOperate">
<el-button @click="openNode">查看</el-button>
<el-button @click="addNode">新增</el-button>
<!-- <el-button @click="addNode">新增</el-button> -->
<el-button @click="editNode">编辑</el-button>
<el-popconfirm @confirm="delNode" title="确认删除?">
<template #reference>
@ -138,6 +136,13 @@
</div>
</template>
</ContextMenu>
<ProtocolComponent
v-model:visible="protocolPartVisible"
:protocol="linkForm.protocol"
:params="linkForm.params"
:disabled="protocolDisabled"
@submit="getProtocolParams"
></ProtocolComponent>
</div>
</template>
@ -164,6 +169,8 @@ import {
} from '/@/api/backend/node/request'
import { getInstitutionalTreeListReq } from '/@/api/backend/org/request'
import { debounce } from 'lodash-es'
import ProtocolComponent from './protocol.vue'
const searchTreeInput = ref('')
const replaceTreeProps = { label: 'nodeName' }
@ -375,7 +382,7 @@ const linkTitle = ref('新增链路')
const originLinkData: linkType = {
id: undefined,
linkName: '',
protocol: '',
protocol: undefined,
params: '',
nodeName: '',
nodeId: '',
@ -385,8 +392,8 @@ const linkFormRef = ref<FormInstance>()
const linkForm = ref<linkType>(JSON.parse(JSON.stringify(originLinkData)))
const linkFormRules = {
linkName: [{ required: true, message: '请输入' + linkKeyEnum['linkName'], trigger: 'blur' }],
protocol: [{ required: true, message: '请输入' + linkKeyEnum['protocol'], trigger: 'blur' }],
params: [{ required: true, message: '请输入' + linkKeyEnum['params'], trigger: 'blur' }],
protocol: [{ required: true, message: '请选择' + linkKeyEnum['protocol'], trigger: 'blur' }],
params: [{ required: true, message: '请配置' + linkKeyEnum['params'], trigger: 'change' }],
nodeId: [{ required: true, message: '请输入' + linkKeyEnum['nodeName'], trigger: 'blur' }],
}
const linkTableData = ref<linkType[]>([])
@ -473,7 +480,12 @@ const getLinkData = (nodeId: string, linkName?: string) => {
getLinkListReq({ nodeId, linkName, pageNum: paginationOptions.current, pageSize: paginationOptions.pageSize })
.then((res) => {
if (res.rows) {
linkTableData.value = res.rows
linkTableData.value = res.rows.map((item) => {
return {
...item,
protocolName: protocolList.find((i) => i.value === item.protocol)?.label,
}
})
paginationOptions.total = res.total
} else {
ElMessage.error(res.msg ?? '查询失败')
@ -483,6 +495,37 @@ const getLinkData = (nodeId: string, linkName?: string) => {
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
})
}
const protocolList = [
// *
{ label: 'IEC104主 *', value: 8 },
{ label: 'IEC104从 *', value: 9 },
{ label: 'MODBUSRTU主 *', value: 12 },
{ label: 'MODBUSTCP主 *', value: 16 },
]
const protocolPartVisible = ref(false)
const protocolDisabled = ref(false)
const getProtocolParams = (val: string) => {
linkForm.value.params = val
}
const openProtocolPart = () => {
if (linkForm.value.protocol) {
protocolDisabled.value = false
protocolPartVisible.value = true
} else {
ElMessage.warning('请先选择协议类型')
}
}
const openParams = (data: linkType) => {
if (data.protocol) {
protocolDisabled.value = true
linkForm.value = { ...data }
protocolPartVisible.value = true
} else {
ElMessage.warning('请先设置协议类型')
}
}
getNodeList().then(() => {
getLinkData(clickTreeData.value!.id!)
})
@ -518,6 +561,10 @@ $paginationHeight: 32px;
}
.tablePart {
height: calc(100% - $paginationHeight);
.el-button {
width: 88px;
height: 32px;
}
}
.tableOperate {
display: flex;
@ -544,7 +591,7 @@ $paginationHeight: 32px;
justify-content: space-between;
align-items: center;
width: 80px;
height: 220px;
height: 176px;
.el-button {
margin: 0;
}

View File

@ -0,0 +1,858 @@
<template>
<el-dialog :model-value="props.visible" :title="currentFormColumn?.label" width="800" @close="closeForm">
<el-form ref="formRef" :model="formData" label-position="left" label-width="200">
<template v-for="(item, index) in Object.keys(currentFormColumn.params)">
<el-card
v-if="Object.keys(currentFormColumn.params[item as formColumnKeyType]).length"
:header="currentFormColumn.cardTitle[index] ?? ''"
class="paramsCard"
>
<el-row>
<template v-for="itemChild in currentFormColumn.params[item as formColumnKeyType]">
<el-col :offset="1" :span="11">
<el-form-item :label="itemChild.data.label" :prop="itemChild.key">
<el-input
v-if="itemChild.data.type === 'input'"
v-model="formData[itemChild.key]"
:disabled="props.disabled"
class="formInput"
></el-input>
<el-input-number
v-else-if="itemChild.data.type === 'number'"
v-model="formData[itemChild.key]"
:disabled="props.disabled"
></el-input-number>
<el-select
v-else-if="itemChild.data.type === 'select'"
v-model="formData[itemChild.key]"
:disabled="props.disabled"
>
<el-option
v-for="opt in itemChild.data.list"
:key="opt.value"
:label="opt.label"
:value="opt.value"
></el-option>
</el-select>
<el-switch
v-else-if="itemChild.data.type === 'check'"
v-model="formData[itemChild.key]"
class="mt-2"
size="large"
inline-prompt
:active-icon="Check"
:inactive-icon="Close"
:disabled="props.disabled"
/>
</el-form-item>
</el-col>
</template>
</el-row>
</el-card>
</template>
</el-form>
<template #footer>
<el-button type="primary" @click="submitForm" :disabled="props.disabled">提交</el-button>
<el-button @click="closeForm">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { Check, Close } from '@element-plus/icons-vue'
import { protocolFormType, formColumnType, formColumnKeyType } from '/@/views/backend/node/type'
import { ElDialog, ElForm, ElFormItem, ElInput, ElInputNumber, ElSelect, ElOption, ElSwitch, ElRow, ElCol, ElCard, ElButton } from 'element-plus'
import { FormInstance } from 'element-plus'
const props = withDefaults(defineProps<{ protocol: number; visible: boolean; params: string; disabled: boolean }>(), {
protocol: 8,
visible: false,
params: '',
disabled: false,
})
const parseParams = ref<protocolFormType>({})
watch(
() => props.visible,
() => {
if (props.params === '') {
formData.value = {}
} else {
parseParams.value = JSON.parse(props.params)
}
}
)
const emits = defineEmits(['update:visible', 'submit'])
const formRef = ref<FormInstance>()
const formData = ref<protocolFormType>({})
// #region
// const cardTitle: ['', ''] = ['', '']
// const netWorkOption = {
// bindAddr: {
// label: '',
// type: 'input',
// value: '1.1.1.1',
// },
// bindPort: {
// label: '',
// type: 'input',
// value: '',
// },
// targetAddr: {
// label: '',
// type: 'input',
// value: '1.1.1.1',
// },
// targetPort: {
// label: '',
// type: 'input',
// value: '',
// },
// socketType: {
// label: '',
// type: 'select',
// value: '0',
// list: [
// { label: 'TCP', value: '0' },
// { label: 'UDP', value: '1' },
// ],
// },
// ignoredSource: {
// label: '',
// type: 'check',
// cardTitle,
// value: true,
// },
// }
// const netWork = JSON.parse(JSON.stringify(netWorkOption))
// delete netWork.socketType
//
// const netWork_common = {
// netWorkOption: {},
// timeOutOption: {},
// otherOption: {
// name: {
// label: '',
// type: 'input',
// value: '',
// },
// state: {
// label: '',
// type: 'select',
// value: 0,
// list: [
// { label: '', value: 0 },
// { label: '', value: 1 },
// ],
// },
// baud: {
// label: '',
// type: 'select',
// value: 9600,
// list: [
// { label: '0', value: 0 },
// { label: '50', value: 50 },
// { label: '75', value: 75 },
// { label: '110', value: 110 },
// { label: '134', value: 134 },
// { label: '150', value: 150 },
// { label: '200', value: 200 },
// { label: '300', value: 300 },
// { label: '600', value: 600 },
// { label: '1200', value: 1200 },
// { label: '1800', value: 1800 },
// { label: '2400', value: 2400 },
// { label: '4800', value: 4800 },
// { label: '9600', value: 9600 },
// { label: '19200', value: 19200 },
// { label: '38400', value: 38400 },
// { label: '57600', value: 57600 },
// { label: '115200', value: 115200 },
// { label: '230400', value: 230400 },
// { label: '460800', value: 460800 },
// { label: '500000', value: 500000 },
// { label: '576000', value: 576000 },
// { label: '921600', value: 921600 },
// ],
// },
// data: {
// label: '',
// type: 'select',
// value: 8,
// list: [
// { label: '5', value: 5 },
// { label: '6', value: 6 },
// { label: '7', value: 7 },
// { label: '8', value: 8 },
// ],
// },
// parity: {
// label: '',
// type: 'select',
// value: 0,
// list: [
// { label: '', value: 0 },
// { label: '', value: 1 },
// { label: '', value: 2 },
// { label: 'MARK', value: 3 },
// { label: 'SPACE', value: 4 },
// ],
// },
// stop: {
// label: '',
// type: 'select',
// value: 1,
// list: [
// { label: '1', value: 1 },
// { label: '2', value: 2 },
// ],
// },
// timeout: {
// label: '',
// type: 'number',
// isSeconds: true,
// value: 1000,
// },
// },
// }
// #endregion
const formColumnList: formColumnType[] = [
{
protocol: 8,
label: 'IEC104主规约参数配置',
cardTitle: ['网络设置', '超时设置'],
params: {
netWorkOption: [
{
key: 'bindAddr',
data: {
label: '绑定地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'bindPort',
data: {
label: '绑定端口',
type: 'input',
value: '',
},
},
{
key: 'targetAddr',
data: {
label: '目标地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'targetPort',
data: {
label: '目标端口',
type: 'input',
value: '',
},
},
{
key: 'ignoredSource',
data: {
label: '忽略地址来源',
type: 'check',
cardTitle: ['网络设置', '超时设置'],
value: true,
},
},
],
timeOutOption: [
{
key: 't0',
data: {
label: '链路断开后重连时间',
isSeconds: true,
type: 'number',
value: 0,
},
},
{
key: 't1',
data: {
label: '发送后未得到认可的超时时间',
isSeconds: true,
type: 'number',
value: 0,
},
},
{
key: 't2',
data: {
label: '最后收到的I帧必须确认的超时时间',
isSeconds: true,
type: 'number',
value: 0,
},
},
{
key: 't3',
data: {
label: '发送测试U帧超时时间',
isSeconds: true,
type: 'number',
value: 0,
},
},
],
otherOption: [
{
key: 'k',
data: {
label: '给定时间未认可的I帧最大值',
type: 'number',
value: 0,
},
},
{
key: 'w',
data: {
label: 'I帧达到此数目时必须给予认可',
type: 'number',
value: 0,
},
},
{
key: 't5',
data: {
label: '召唤电度量间隔',
type: 'input',
value: '',
},
},
{
key: 'irn',
data: {
label: '资产编码irn',
type: 'input',
value: '',
},
},
{
key: 't4',
data: {
label: '是否使用循环总召唤',
type: 'check',
value: true,
},
},
{
key: 'useCycleInterrogationCommand',
data: {
label: '总召唤间隔',
type: 'input',
value: '',
},
},
],
},
},
{
protocol: 9,
label: 'IEC104从规约参数配置',
cardTitle: ['网络设置', '超时设置'],
params: {
netWorkOption: [
{
key: 'bindAddr',
data: {
label: '绑定地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'bindPort',
data: {
label: '绑定端口',
type: 'input',
value: '',
},
},
{
key: 'targetAddr',
data: {
label: '目标地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'targetPort',
data: {
label: '目标端口',
type: 'input',
value: '',
},
},
{
key: 'ignoredSource',
data: {
label: '忽略地址来源',
type: 'check',
cardTitle: ['网络设置', '超时设置'],
value: true,
},
},
],
timeOutOption: [
{
key: 't0',
data: {
label: '链路断开后重连时间',
type: 'number',
value: 0,
},
},
{
key: 't1',
data: {
label: '发送后未得到认可的超时时间',
type: 'number',
value: 0,
},
},
{
key: 't2',
data: {
label: '最后收到的I帧必须确认的超时时间',
type: 'number',
isSeconds: true,
value: 0,
},
},
{
key: 't3',
data: {
label: '发送测试U帧超时时间',
type: 'number',
isSeconds: true,
value: 0,
},
},
],
otherOption: [
{
key: 'k',
data: {
label: '给定时间未认可的I帧最大值',
type: 'number',
value: 0,
},
},
{
key: 'w',
data: {
label: 'I帧达到此数目时必须给予认可',
type: 'number',
value: 0,
},
},
{
key: 'ycType',
data: {
label: '默认遥测类型',
type: 'select',
value: '0',
list: [
{
label: '归一化值',
value: '0',
},
{
label: '短浮点值',
value: '1',
},
{
label: '标度化值',
value: '2',
},
{
label: '不带品质归一化值',
value: '3',
},
],
},
},
{
key: 'irn',
data: {
label: '资产编码',
type: 'input',
value: '',
},
},
{
key: 'sendTestType',
data: {
label: '使用发送测试报文类型',
type: 'select',
value: '1',
list: [
{
label: '测试命令',
value: '0',
},
{
label: '带CP56Time2a的测试命令',
value: '1',
},
],
},
},
{
key: 'useSendTest',
data: {
label: '是否使用发送测试报文类型',
type: 'check',
value: false,
},
},
{
key: 'useSendEndOfInitialisation',
data: {
label: '发送初始化结束帧',
type: 'check',
value: false,
},
},
{
key: 'sendStartDt',
data: {
label: '厂站发起启动帧',
type: 'check',
value: false,
},
},
{
key: 'useNsNrCheck',
data: {
label: '检查接收发送计数',
type: 'check',
value: false,
},
},
],
},
},
{
protocol: 12,
label: 'MODBUSRTU主 *',
cardTitle: ['网络设置', '超时设置'],
params: {
netWorkOption: [],
timeOutOption: [],
otherOption: [
{
key: 'name',
data: {
label: '串口名称',
type: 'input',
value: '',
},
},
{
key: 'state',
data: {
label: '状态',
type: 'select',
value: 0,
list: [
{
label: 'OFF',
value: 0,
},
{
label: 'ON',
value: 1,
},
],
},
},
{
key: 'baud',
data: {
label: '波特率',
type: 'select',
value: 9600,
list: [
{
label: '0',
value: 0,
},
{
label: '50',
value: 50,
},
{
label: '75',
value: 75,
},
{
label: '110',
value: 110,
},
{
label: '134',
value: 134,
},
{
label: '150',
value: 150,
},
{
label: '200',
value: 200,
},
{
label: '300',
value: 300,
},
{
label: '600',
value: 600,
},
{
label: '1200',
value: 1200,
},
{
label: '1800',
value: 1800,
},
{
label: '2400',
value: 2400,
},
{
label: '4800',
value: 4800,
},
{
label: '9600',
value: 9600,
},
{
label: '19200',
value: 19200,
},
{
label: '38400',
value: 38400,
},
{
label: '57600',
value: 57600,
},
{
label: '115200',
value: 115200,
},
{
label: '230400',
value: 230400,
},
{
label: '460800',
value: 460800,
},
{
label: '500000',
value: 500000,
},
{
label: '576000',
value: 576000,
},
{
label: '921600',
value: 921600,
},
],
},
},
{
key: 'data',
data: {
label: '数据位',
type: 'select',
value: 8,
list: [
{
label: '5',
value: 5,
},
{
label: '6',
value: 6,
},
{
label: '7',
value: 7,
},
{
label: '8',
value: 8,
},
],
},
},
{
key: 'parity',
data: {
label: '校验位',
type: 'select',
value: 0,
list: [
{
label: '无校验',
value: 0,
},
{
label: '奇校验',
value: 1,
},
{
label: '偶校验',
value: 2,
},
],
},
},
{
key: 'stop',
data: {
label: '停止位',
type: 'select',
value: 1,
list: [
{
label: '1',
value: 1,
},
{
label: '2',
value: 2,
},
],
},
},
{
key: 'timeout',
data: {
label: '超时时间',
type: 'number',
isSeconds: true,
value: 1000,
},
},
],
},
},
{
protocol: 16,
label: '网络参数配置',
cardTitle: ['网络设置', '超时设置'],
params: {
netWorkOption: [
{
key: 'bindAddr',
data: {
label: '绑定地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'bindPort',
data: {
label: '绑定端口',
type: 'input',
value: '',
},
},
{
key: 'targetAddr',
data: {
label: '目标地址',
type: 'input',
value: '1.1.1.1',
},
},
{
key: 'targetPort',
data: {
label: '目标端口',
type: 'input',
value: '',
},
},
{
key: 'socketType',
data: {
label: '网络类型',
type: 'select',
value: '0',
list: [
{
label: 'TCP',
value: '0',
},
{
label: 'UDP',
value: '1',
},
],
},
},
{
key: 'ignoredSource',
data: {
label: '忽略地址来源',
type: 'check',
cardTitle: ['网络设置', '超时设置'],
value: true,
},
},
],
timeOutOption: [],
otherOption: [],
},
},
]
const currentFormColumn = computed(() => {
const data = formColumnList.find((item) => item.protocol === props.protocol)!
const currentFormKeyObj: protocolFormType = {}
Object.keys(data.params).forEach((key) => {
data.params[key as formColumnKeyType].forEach((item) => {
currentFormKeyObj[item.key] = parseParams.value?.[item.key] as any
})
})
formData.value = currentFormKeyObj
return data
})
const submitForm = () => {
emits('submit', JSON.stringify(formData.value))
emits('update:visible', false)
}
const closeForm = () => {
formRef.value?.resetFields()
formData.value = {}
emits('update:visible', false)
}
</script>
<style scoped>
.paramsCard {
margin: 10px;
}
</style>

View File

@ -49,7 +49,8 @@ export enum linkKeyEnum {
export type linkType = {
id?: string
linkName: string
protocol: string
protocol?: number
protocolName?:string
params: string
nodeName: string
nodeId: string
@ -66,3 +67,65 @@ export type addLinkType = Pick<linkType, 'linkName' | 'protocol' | 'params' | 'n
export type updateLinkType = Pick<linkType, 'id' | 'linkName' | 'protocol' | 'params' | 'nodeName' | 'nodeId' | 'revision'>
export type delLinkType = Pick<linkType, 'id'>
export type netWorkOptionType = {
bindAddr?: string
bindPort?: string
targetAddr?: string
targetPort?: string
socketType?: '0' | '1'
ignoredSource?: boolean
}
export type timeOutOptionType = {
t0?: number
t1?: number
t2?: number
t3?: number
}
export type otherOptionType = {
k?: number
w?: number
t5?: string
irn?: string
t4?: boolean
useCycleInterrogationCommand?: string
ycType?: '0' | '1' | '2' | '3'
sendTestType?: '0' | '1'
useSendTest?: boolean
useSendEndOfInitialisation?: boolean
sendStartDt?: boolean
useNsNrCheck?: boolean
name?: string
state?: string
baud?: number
data?: number
parity?: number
stop?: number
timeout?: number
}
export type protocolFormType = netWorkOptionType & timeOutOptionType & otherOptionType
type paramsType = {
key: keyof protocolFormType
data: {
label: string
type: string
value: number | string | boolean
isSeconds?: boolean
list?: { label: string; value: string | number }[]
cardTitle?: ['网络设置', '超时设置']
}
}
export type formColumnType = {
protocol: number
label: string
cardTitle: ['网络设置', '超时设置']
params: {
netWorkOption: paramsType[]
timeOutOption: paramsType[]
otherOption: paramsType[]
}
}
export type formColumnKeyType = keyof formColumnType['params']