2025-08-26 20:52:24 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
2025-09-22 15:26:13 +08:00
|
|
|
|
<div class="flow-container" style="overflow: hidden; position: relative"
|
|
|
|
|
|
:style="{ height: vueFlowElement + 'px' }">
|
2025-08-26 20:52:24 +08:00
|
|
|
|
<!-- <el-button @click="logConnections">打印当前配对</el-button> -->
|
2025-09-22 15:26:13 +08:00
|
|
|
|
<VueFlow :nodes="nodes" :edges="edges" :connection-radius="30" :nodes-draggable="false" :dragging="false"
|
|
|
|
|
|
:zoom-on-scroll="false" :pan-on-drag="false" :disable-zoom-pan-on-connect="true"
|
|
|
|
|
|
:prevent-scrolling="true" :fit-view="true" :min-zoom="1" :max-zoom="1"
|
|
|
|
|
|
:nodesConnectable="checkStore.nodesConnectable" :elements-selectable="false" auto-connect
|
|
|
|
|
|
@connect="handleConnect" @connect-start="handleConnectStart" @connect-end="handleConnectEnd"
|
2025-10-23 14:41:08 +08:00
|
|
|
|
@pane-ready="onPaneReady" @node-double-click="handleNodeDoubleClick" v-on:pane-mouse-move="false"></VueFlow>
|
2025-08-26 20:52:24 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部操作按钮 -->
|
|
|
|
|
|
<!-- <template #footer>
|
|
|
|
|
|
<div class="dialog-footer">
|
|
|
|
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
|
|
|
|
<el-button type="primary" @click="handleNext">下一步</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template> -->
|
|
|
|
|
|
<!-- 手动检测-勾选检测项弹窗 -->
|
|
|
|
|
|
<!-- <SelectTestItemPopup ref="selectTestItemPopupRef" @openTestDialog="openTestDialog"></SelectTestItemPopup> -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-10-16 09:36:43 +08:00
|
|
|
|
import { h, ref, onMounted, PropType, computed } from 'vue'
|
2025-08-26 20:52:24 +08:00
|
|
|
|
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
|
|
|
|
|
import { dialogBig } from '@/utils/elementBind'
|
|
|
|
|
|
import { Platform, Flag } from '@element-plus/icons-vue'
|
|
|
|
|
|
import { Device } from '@/api/device/interface/device'
|
|
|
|
|
|
import { StandardDevice } from '@/api/device/interface/standardDevice'
|
|
|
|
|
|
import SelectTestItemPopup from '@/views/home/components/selectTestItemPopup.vue'
|
|
|
|
|
|
import { ElMessage, stepProps } from 'element-plus'
|
|
|
|
|
|
import CustomEdge from './RemoveableEdge.vue' // 导入自定义连接线组件
|
|
|
|
|
|
import { jwtUtil } from '@/utils/jwtUtil'
|
|
|
|
|
|
import { useCheckStore } from '@/stores/modules/check'
|
2025-10-21 10:43:27 +08:00
|
|
|
|
import { ipc } from '@/utils/ipcRenderer'
|
2025-10-23 16:28:13 +08:00
|
|
|
|
import { fa, tr } from 'element-plus/es/locale'
|
2025-11-26 15:06:50 +08:00
|
|
|
|
import { CheckData } from '@/api/check/interface'
|
2025-09-08 16:01:04 +08:00
|
|
|
|
const vueFlowElement = ref(442)
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const checkStore = useCheckStore()
|
|
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
|
|
const selectTestItemPopupRef = ref<InstanceType<typeof SelectTestItemPopup>>()
|
|
|
|
|
|
const testPopup = ref()
|
|
|
|
|
|
const dialogTitle = ref('手动检测')
|
|
|
|
|
|
const prop = defineProps({
|
|
|
|
|
|
devIdList: {
|
|
|
|
|
|
type: Array as any,
|
|
|
|
|
|
default: []
|
|
|
|
|
|
},
|
|
|
|
|
|
pqStandardDevList: {
|
|
|
|
|
|
type: Array as any,
|
|
|
|
|
|
default: []
|
|
|
|
|
|
},
|
|
|
|
|
|
planIdKey: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: ''
|
2025-09-17 14:08:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
deviceMonitor: {
|
|
|
|
|
|
type: Map as PropType<Map<string, any[]>>,
|
|
|
|
|
|
default: () => new Map()
|
2025-10-16 09:36:43 +08:00
|
|
|
|
},
|
|
|
|
|
|
dialogWidth: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 0
|
2025-09-08 16:01:04 +08:00
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
})
|
|
|
|
|
|
// 计算对话框高度
|
|
|
|
|
|
const dialogHeight = ref(600)
|
2025-08-27 11:17:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
// 初始化 VueFlow,注册自定义连线类型
|
2025-10-23 16:28:13 +08:00
|
|
|
|
const { edges, setViewport,removeEdges } = useVueFlow({
|
2025-08-26 20:52:24 +08:00
|
|
|
|
edgeTypes: {
|
|
|
|
|
|
default: CustomEdge
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-10-23 14:41:08 +08:00
|
|
|
|
|
|
|
|
|
|
const handleNodeDoubleClick = (event: any) => {
|
|
|
|
|
|
const { node } = event
|
|
|
|
|
|
|
|
|
|
|
|
// 判断节点类型
|
|
|
|
|
|
if (node.type === 'input') {
|
|
|
|
|
|
// 被检通道节点,检查是否已经连接
|
|
|
|
|
|
const isConnected = edges.value.some(edge => edge.source === node.id)
|
|
|
|
|
|
|
|
|
|
|
|
if (isConnected) {
|
|
|
|
|
|
ElMessage.warning('该被检通道已经连接,不能重复连接')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 寻找未连接的标准通道节点(优先寻找未被连接的标准通道)
|
|
|
|
|
|
const targetNodes = nodes.value.filter(n => n.type === 'output')
|
|
|
|
|
|
|
|
|
|
|
|
// 首先尝试连接尚未被连接的标准通道
|
|
|
|
|
|
for (const targetNode of targetNodes) {
|
|
|
|
|
|
const isTargetConnected = edges.value.some(edge => edge.target === targetNode.id)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isTargetConnected) {
|
|
|
|
|
|
// 检查是否已存在连接(虽然这里应该不会存在)
|
|
|
|
|
|
const isAlreadyConnected = edges.value.some(edge =>
|
|
|
|
|
|
edge.source === node.id && edge.target === targetNode.id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isAlreadyConnected) {
|
|
|
|
|
|
const newEdge = {
|
|
|
|
|
|
id: `edge-${node.id}-${targetNode.id}`,
|
|
|
|
|
|
source: node.id,
|
|
|
|
|
|
target: targetNode.id,
|
|
|
|
|
|
type: 'default'
|
|
|
|
|
|
}
|
|
|
|
|
|
edges.value.push(newEdge)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果所有标准通道都已被连接,尝试连接已被连接但连接的是其他被检通道的标准通道
|
|
|
|
|
|
for (const targetNode of targetNodes) {
|
|
|
|
|
|
// 检查是否已存在连接
|
|
|
|
|
|
const isAlreadyConnected = edges.value.some(edge =>
|
|
|
|
|
|
edge.source === node.id && edge.target === targetNode.id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isAlreadyConnected) {
|
|
|
|
|
|
const isTargetConnected = edges.value.some(edge => edge.target === targetNode.id)
|
|
|
|
|
|
|
|
|
|
|
|
// 如果标准通道已被连接,但不是连接到当前被检通道,则不能连接
|
|
|
|
|
|
if (isTargetConnected) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const newEdge = {
|
|
|
|
|
|
id: `edge-${node.id}-${targetNode.id}`,
|
|
|
|
|
|
source: node.id,
|
|
|
|
|
|
target: targetNode.id,
|
|
|
|
|
|
type: 'default'
|
|
|
|
|
|
}
|
|
|
|
|
|
edges.value.push(newEdge)
|
|
|
|
|
|
ElMessage.success(`已自动连接到 ${targetNode.data.label.children[1].children[0].children[0].replace('设备名称:', '')} 的标准通道`)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ElMessage.warning('没有可用的标准通道进行连接')
|
|
|
|
|
|
} else if (node.type === 'output') {
|
|
|
|
|
|
// 标准通道节点,检查是否已经连接
|
|
|
|
|
|
const isConnected = edges.value.some(edge => edge.target === node.id)
|
|
|
|
|
|
|
|
|
|
|
|
if (isConnected) {
|
|
|
|
|
|
ElMessage.warning('该标准通道已经连接,不能重复连接')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 寻找未连接的被检通道节点(优先寻找未被连接的被检通道)
|
|
|
|
|
|
const sourceNodes = nodes.value.filter(n => n.type === 'input')
|
|
|
|
|
|
|
|
|
|
|
|
// 首先尝试连接尚未被连接的被检通道
|
|
|
|
|
|
for (const sourceNode of sourceNodes) {
|
|
|
|
|
|
const isSourceConnected = edges.value.some(edge => edge.source === sourceNode.id)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isSourceConnected) {
|
|
|
|
|
|
// 检查是否已存在连接(虽然这里应该不会存在)
|
|
|
|
|
|
const isAlreadyConnected = edges.value.some(edge =>
|
|
|
|
|
|
edge.source === sourceNode.id && edge.target === node.id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isAlreadyConnected) {
|
|
|
|
|
|
const newEdge = {
|
|
|
|
|
|
id: `edge-${sourceNode.id}-${node.id}`,
|
|
|
|
|
|
source: sourceNode.id,
|
|
|
|
|
|
target: node.id,
|
|
|
|
|
|
type: 'default'
|
|
|
|
|
|
}
|
|
|
|
|
|
edges.value.push(newEdge)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果所有被检通道都已被连接,尝试连接已被连接但连接的是其他标准通道的被检通道
|
|
|
|
|
|
for (const sourceNode of sourceNodes) {
|
|
|
|
|
|
// 检查是否已存在连接
|
|
|
|
|
|
const isAlreadyConnected = edges.value.some(edge =>
|
|
|
|
|
|
edge.source === sourceNode.id && edge.target === node.id
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (!isAlreadyConnected) {
|
|
|
|
|
|
const isSourceConnected = edges.value.some(edge => edge.source === sourceNode.id)
|
|
|
|
|
|
|
|
|
|
|
|
// 如果被检通道已被连接,但不是连接到当前标准通道,则不能连接
|
|
|
|
|
|
if (isSourceConnected) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const newEdge = {
|
|
|
|
|
|
id: `edge-${sourceNode.id}-${node.id}`,
|
|
|
|
|
|
source: sourceNode.id,
|
|
|
|
|
|
target: node.id,
|
|
|
|
|
|
type: 'default'
|
|
|
|
|
|
}
|
|
|
|
|
|
edges.value.push(newEdge)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ElMessage.warning('没有可用的被检通道进行连接')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
// 初始化时锁定画布位置
|
|
|
|
|
|
const onPaneReady = () => {
|
|
|
|
|
|
setViewport({ x: 0, y: 0, zoom: 1 })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提取公共的label渲染函数
|
2025-10-21 10:43:27 +08:00
|
|
|
|
const createLabel = (device:any, Key: number) => {
|
2025-08-26 20:52:24 +08:00
|
|
|
|
return h(
|
|
|
|
|
|
'div',
|
|
|
|
|
|
{
|
|
|
|
|
|
style: {
|
|
|
|
|
|
display: 'flex',
|
2025-09-08 16:01:04 +08:00
|
|
|
|
// flexDirection: 'column',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
fontSize: '15px',
|
2025-09-08 16:01:04 +08:00
|
|
|
|
height: '75px',
|
2025-08-27 11:17:13 +08:00
|
|
|
|
// textAlign: 'center',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
border: '1px solid #ccc',
|
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
|
padding: '8px',
|
|
|
|
|
|
backgroundColor: '#f9f9f9'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
[
|
2025-09-08 16:01:04 +08:00
|
|
|
|
// h(Platform, {
|
|
|
|
|
|
// style: {
|
|
|
|
|
|
// height: '40px',
|
|
|
|
|
|
// marginBottom: '4px',
|
|
|
|
|
|
// color: '#526ade'
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }),
|
|
|
|
|
|
h('img', {
|
|
|
|
|
|
src:
|
|
|
|
|
|
Key == 2
|
|
|
|
|
|
? new URL('@/assets/images/inspected1.jpg', import.meta.url).href
|
|
|
|
|
|
: new URL('@/assets/images/inspected2.png', import.meta.url).href,
|
|
|
|
|
|
// alt: '设备图标',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
style: {
|
2025-09-08 16:01:04 +08:00
|
|
|
|
width: '50px',
|
|
|
|
|
|
marginRight: '5px'
|
|
|
|
|
|
// 保持原有的颜色风格,如果需要可以调整滤镜
|
|
|
|
|
|
// filter: 'invert(35%) sepia(65%) saturate(300%) hue-rotate(210deg)'
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
}),
|
2025-10-21 10:43:27 +08:00
|
|
|
|
h('div', { style: { textAlign: 'left' } }, ['设备名称:' + device.name,
|
|
|
|
|
|
h('br'),
|
|
|
|
|
|
'设备类型:' + device.deviceType,
|
|
|
|
|
|
h('br'),
|
|
|
|
|
|
'Ip地址:' + device.ip,
|
|
|
|
|
|
|
|
|
|
|
|
])
|
2025-08-27 11:17:13 +08:00
|
|
|
|
// h('div', null, '设备名称:' + text),
|
|
|
|
|
|
// h('div', null, '设备类型:' + type)
|
2025-08-26 20:52:24 +08:00
|
|
|
|
]
|
|
|
|
|
|
) as any
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const createLabel3 = (text: string) => {
|
|
|
|
|
|
return h(
|
|
|
|
|
|
'div',
|
|
|
|
|
|
{
|
|
|
|
|
|
style: {
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
fontSize: '15px',
|
2025-09-08 16:01:04 +08:00
|
|
|
|
height: '35px',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
border: '1px solid #ccc',
|
|
|
|
|
|
borderRadius: '8px',
|
2025-09-08 16:01:04 +08:00
|
|
|
|
// padding: '8px',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
backgroundColor: '#f9f9f9'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
[
|
2025-09-08 16:01:04 +08:00
|
|
|
|
h('div', {
|
2025-08-26 20:52:24 +08:00
|
|
|
|
style: {
|
2025-09-08 16:01:04 +08:00
|
|
|
|
width: '8px',
|
2025-08-26 20:52:24 +08:00
|
|
|
|
marginRight: '4px',
|
|
|
|
|
|
color: '#526ade'
|
|
|
|
|
|
}
|
|
|
|
|
|
}),
|
|
|
|
|
|
text
|
|
|
|
|
|
]
|
|
|
|
|
|
) as any
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleConnectStart = (params: any) => {
|
|
|
|
|
|
onPaneReady()
|
2025-10-23 16:28:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-23 16:28:13 +08:00
|
|
|
|
// const handleConnectEnd = (params: any) => {
|
|
|
|
|
|
// console.log('handleConnectEnd',edges.value,edges.value.length)
|
|
|
|
|
|
// onPaneReady()
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// const handleConnect = (params: any) => {
|
|
|
|
|
|
// const sourceNode = nodes.value.find(node => node.id === params.source)
|
|
|
|
|
|
// const targetNode = nodes.value.find(node => node.id === params.target)
|
|
|
|
|
|
// const isValidConnection = sourceNode?.type === 'input' && targetNode?.type === 'output'
|
|
|
|
|
|
// if (!isValidConnection) {
|
|
|
|
|
|
// removeEdge(params)
|
|
|
|
|
|
// ElMessage.warning('只能从被检通道连接到标准通道')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 过滤掉当前连接,检查是否还有重复的
|
|
|
|
|
|
// const existingEdges = edges.value.filter(edge => edge.source === params.source || edge.target === params.target)
|
|
|
|
|
|
|
|
|
|
|
|
// // 如果同源或同目标的连接超过1个,说明有重复
|
|
|
|
|
|
// if (existingEdges.length > 1) {
|
|
|
|
|
|
// const duplicateSource = existingEdges.filter(edge => edge.source === params.source).length > 1
|
|
|
|
|
|
// const duplicateTarget = existingEdges.filter(edge => edge.target === params.target).length > 1
|
|
|
|
|
|
|
|
|
|
|
|
// if (duplicateSource) {
|
|
|
|
|
|
// removeEdge(params)
|
|
|
|
|
|
// ElMessage.warning('该被检通道已经连接,不能重复连接')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (duplicateTarget) {
|
|
|
|
|
|
// removeEdge(params)
|
|
|
|
|
|
// ElMessage.warning('该标准通道已经连接,不能重复连接')
|
|
|
|
|
|
// return
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // 删除不合法连接
|
|
|
|
|
|
// const removeEdge = (params: any) => {
|
|
|
|
|
|
// // console.log('删除不合法连接:', params);
|
|
|
|
|
|
// // console.log('删除连接信息:', edges.value);
|
|
|
|
|
|
// // console.log('11111===', edges.value.length);
|
|
|
|
|
|
// const edgeIndex = edges.value.findIndex(edge => edge.source === params.source && edge.target === params.target)
|
|
|
|
|
|
// console.log('删除连接索引:', edgeIndex);
|
|
|
|
|
|
// if (edgeIndex !== -1) {
|
|
|
|
|
|
// edges.value.splice(edgeIndex , 1)
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加一个响应式变量来存储需要删除的连接信息
|
|
|
|
|
|
const pendingRemoveEdge = ref<any>(null)
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const handleConnectEnd = (params: any) => {
|
2025-10-23 16:28:13 +08:00
|
|
|
|
// 在连接结束时检查是否有待删除的连接
|
|
|
|
|
|
if (pendingRemoveEdge.value) {
|
|
|
|
|
|
removeEdge(pendingRemoveEdge.value)
|
|
|
|
|
|
pendingRemoveEdge.value = null // 清空待删除连接
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
onPaneReady()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleConnect = (params: any) => {
|
|
|
|
|
|
const sourceNode = nodes.value.find(node => node.id === params.source)
|
|
|
|
|
|
const targetNode = nodes.value.find(node => node.id === params.target)
|
|
|
|
|
|
const isValidConnection = sourceNode?.type === 'input' && targetNode?.type === 'output'
|
2025-10-23 16:28:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
if (!isValidConnection) {
|
2025-10-23 16:28:13 +08:00
|
|
|
|
// 设置待删除连接而不是立即删除
|
|
|
|
|
|
pendingRemoveEdge.value = params
|
2025-08-26 20:52:24 +08:00
|
|
|
|
ElMessage.warning('只能从被检通道连接到标准通道')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-23 16:32:41 +08:00
|
|
|
|
// 检查是否已经存在完全相同的连接(精确匹配源和目标)
|
|
|
|
|
|
const isAlreadyConnected = edges.value.some(edge =>
|
|
|
|
|
|
edge.source === params.source && edge.target === params.target
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (isAlreadyConnected) {
|
|
|
|
|
|
// 设置待删除连接而不是立即删除
|
|
|
|
|
|
pendingRemoveEdge.value = params
|
|
|
|
|
|
ElMessage.warning('这两个通道已经连接,不能重复连接')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
2025-10-23 16:32:41 +08:00
|
|
|
|
// 检查源节点是否已经被连接(一个被检通道只能连接一个标准通道)
|
|
|
|
|
|
const isSourceConnected = edges.value.some(edge => edge.source === params.source)
|
|
|
|
|
|
if (isSourceConnected) {
|
|
|
|
|
|
// 设置待删除连接而不是立即删除
|
|
|
|
|
|
pendingRemoveEdge.value = params
|
|
|
|
|
|
ElMessage.warning('该被检通道已经连接,不能重复连接')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
2025-10-23 16:32:41 +08:00
|
|
|
|
// 检查目标节点是否已经被连接(一个标准通道只能连接一个被检通道)
|
|
|
|
|
|
const isTargetConnected = edges.value.some(edge => edge.target === params.target)
|
|
|
|
|
|
if (isTargetConnected) {
|
|
|
|
|
|
// 设置待删除连接而不是立即删除
|
|
|
|
|
|
pendingRemoveEdge.value = params
|
|
|
|
|
|
ElMessage.warning('该标准通道已经连接,不能重复连接')
|
|
|
|
|
|
return
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
2025-10-23 16:28:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 如果没有问题,清空待删除连接
|
|
|
|
|
|
pendingRemoveEdge.value = null
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除不合法连接
|
|
|
|
|
|
const removeEdge = (params: any) => {
|
2025-10-23 14:41:08 +08:00
|
|
|
|
const edgeIndex = edges.value.findIndex(edge => edge.source === params.source && edge.target === params.target)
|
2025-10-23 16:28:13 +08:00
|
|
|
|
|
|
|
|
|
|
if (edgeIndex !== -1) {
|
|
|
|
|
|
edges.value.splice(edgeIndex, 1)
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const nodes = ref([])
|
|
|
|
|
|
const planId = ref('')
|
|
|
|
|
|
const devIds = ref<string[]>()
|
|
|
|
|
|
const standardDevIds = ref<string[]>()
|
|
|
|
|
|
|
|
|
|
|
|
const open = async () => {
|
|
|
|
|
|
edges.value = []
|
2025-10-21 10:43:27 +08:00
|
|
|
|
|
2025-11-26 15:06:50 +08:00
|
|
|
|
//devIds.value = prop.devIdList.map(d => d.id)
|
2025-08-26 20:52:24 +08:00
|
|
|
|
standardDevIds.value = prop.pqStandardDevList.map(d => d.id)
|
|
|
|
|
|
planId.value = prop.planIdKey
|
2025-09-22 15:26:13 +08:00
|
|
|
|
nodes.value = createNodes(prop.devIdList, prop.pqStandardDevList, prop.deviceMonitor)
|
2025-08-26 20:52:24 +08:00
|
|
|
|
dialogVisible.value = true
|
|
|
|
|
|
onPaneReady()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
open()
|
|
|
|
|
|
})
|
|
|
|
|
|
const handleNext = async () => {
|
|
|
|
|
|
if (edges.value.length === 0) {
|
|
|
|
|
|
ElMessage.warning('请先完成通道配对')
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
// const sourceKey = edge.source.replace('被检通道-', '').replace('-', '_');
|
|
|
|
|
|
let chnNumList: string[] = []
|
|
|
|
|
|
await edges.value.forEach(edge => {
|
|
|
|
|
|
const match = edge.source.split('-')
|
|
|
|
|
|
if (match) {
|
2025-11-26 15:06:50 +08:00
|
|
|
|
chnNumList.push(match[1] + '-'+ match[2])
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-11-26 15:06:50 +08:00
|
|
|
|
|
|
|
|
|
|
const connectedDeviceIds = [...new Set(chnNumList.map(item => item.split('-')[0]))]
|
|
|
|
|
|
devIds.value = connectedDeviceIds
|
|
|
|
|
|
//可能存在勾选的被检设备未连线的情况,需要过滤掉
|
|
|
|
|
|
let devices: CheckData.Device[] = prop.devIdList
|
|
|
|
|
|
.filter((item: any) => connectedDeviceIds.includes(item.id))
|
|
|
|
|
|
.map((item: any) => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
deviceId: item.id,
|
|
|
|
|
|
deviceName: item.name,
|
|
|
|
|
|
chnNum: item.devChns,
|
|
|
|
|
|
planId: item.planId,
|
|
|
|
|
|
deviceType: item.devType,
|
|
|
|
|
|
devVolt: item.devVolt,
|
|
|
|
|
|
devCurr: item.devCurr,
|
|
|
|
|
|
factorFlag: item.factorFlag,
|
|
|
|
|
|
checkResult: item.checkResult
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
checkStore.clearDevices()
|
|
|
|
|
|
checkStore.addDevices(devices)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const connections = edges.value.reduce(
|
|
|
|
|
|
(map, edge) => {
|
|
|
|
|
|
// 从source中提取设备ID和通道号: 被检通道-{deviceId}-{channelNum} => {deviceId}-{channelNum}
|
|
|
|
|
|
const sourceKey = edge.source.replace('被检通道-', '').replace('-', '_')
|
|
|
|
|
|
|
|
|
|
|
|
// 从target中提取设备ID和通道号: 标准通道-{deviceId}-{channelNum} => {deviceId}-{channelNum}
|
|
|
|
|
|
const targetValue = edge.target.replace('标准通道-', '').replace('-', '_')
|
|
|
|
|
|
|
|
|
|
|
|
map[sourceKey] = targetValue
|
|
|
|
|
|
return map
|
|
|
|
|
|
},
|
|
|
|
|
|
{} as Record<string, string>
|
|
|
|
|
|
)
|
2025-08-27 14:55:00 +08:00
|
|
|
|
await generateChannelMapping()
|
2025-09-17 15:42:05 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
await checkStore.setChnNum(chnNumList)
|
|
|
|
|
|
return {
|
|
|
|
|
|
title: dialogTitle.value,
|
|
|
|
|
|
mapping: channelMapping.value,
|
|
|
|
|
|
plan: planId.value,
|
|
|
|
|
|
login: jwtUtil.getLoginName(),
|
|
|
|
|
|
devIdsArray: devIds.value,
|
|
|
|
|
|
standardDevIdsArray: standardDevIds.value,
|
|
|
|
|
|
pair: connections
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const openTestDialog = async () => {
|
|
|
|
|
|
// 转换连接信息,只保留设备ID和通道号
|
|
|
|
|
|
const connections = edges.value.reduce(
|
|
|
|
|
|
(map, edge) => {
|
|
|
|
|
|
// 从source中提取设备ID和通道号: 被检通道-{deviceId}-{channelNum} => {deviceId}-{channelNum}
|
|
|
|
|
|
const sourceKey = edge.source.replace('被检通道-', '').replace('-', '_')
|
|
|
|
|
|
|
|
|
|
|
|
// 从target中提取设备ID和通道号: 标准通道-{deviceId}-{channelNum} => {deviceId}-{channelNum}
|
|
|
|
|
|
const targetValue = edge.target.replace('标准通道-', '').replace('-', '_')
|
|
|
|
|
|
|
|
|
|
|
|
map[sourceKey] = targetValue
|
|
|
|
|
|
return map
|
|
|
|
|
|
},
|
|
|
|
|
|
{} as Record<string, string>
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
generateChannelMapping()
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
testPopup.value?.open(
|
|
|
|
|
|
dialogTitle.value,
|
|
|
|
|
|
channelMapping.value,
|
|
|
|
|
|
planId.value,
|
|
|
|
|
|
jwtUtil.getLoginName(),
|
|
|
|
|
|
devIds.value,
|
|
|
|
|
|
standardDevIds.value,
|
|
|
|
|
|
connections
|
|
|
|
|
|
)
|
|
|
|
|
|
}, 100)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换 edges.value 为 channelMapping 格式
|
|
|
|
|
|
const channelMapping = ref<Record<string, Record<string, string>>>({})
|
|
|
|
|
|
|
|
|
|
|
|
// 生成映射关系的方法
|
|
|
|
|
|
const generateChannelMapping = () => {
|
|
|
|
|
|
const mapping: Record<string, Record<string, string>> = {}
|
|
|
|
|
|
|
|
|
|
|
|
edges.value.forEach(edge => {
|
|
|
|
|
|
// 解析 source 节点信息(被检通道)
|
|
|
|
|
|
const sourceParts = edge.source.split('-')
|
|
|
|
|
|
const sourceDeviceId = sourceParts[1]
|
|
|
|
|
|
const sourceChannel = sourceParts[2]
|
|
|
|
|
|
|
|
|
|
|
|
// 解析 target 节点信息(标准通道)
|
|
|
|
|
|
const targetParts = edge.target.split('-')
|
|
|
|
|
|
const targetDeviceId = targetParts[1]
|
|
|
|
|
|
const targetChannel = targetParts[2]
|
|
|
|
|
|
|
|
|
|
|
|
// 查找对应的节点以获取显示名称
|
|
|
|
|
|
const sourceDeviceNode = nodes.value.find(node => node.id === sourceDeviceId)
|
2025-08-27 14:55:00 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const targetDeviceNode = nodes.value.find(node => node.id === targetDeviceId)
|
|
|
|
|
|
|
|
|
|
|
|
if (sourceDeviceNode && targetDeviceNode) {
|
|
|
|
|
|
// 提取设备显示文本
|
2025-08-27 14:55:00 +08:00
|
|
|
|
const sourceDeviceText = sourceDeviceNode.data.label.children[1].children[0].children
|
|
|
|
|
|
const targetDeviceText = targetDeviceNode.data.label.children[1].children[0].children
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
|
|
|
|
|
// 构造键名 - 现在以标准设备为键
|
|
|
|
|
|
const targetKey = `${targetDeviceText}`.replace('设备名称:', '')
|
|
|
|
|
|
const sourceValue = `${sourceDeviceText}通道${sourceChannel}`.replace('设备名称:', '')
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化对象
|
|
|
|
|
|
if (!mapping[targetKey]) {
|
|
|
|
|
|
mapping[targetKey] = {}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加映射关系 - 标准设备通道 -> 被检设备信息
|
|
|
|
|
|
mapping[targetKey][`通道${targetChannel}`] = sourceValue
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
channelMapping.value = mapping
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-16 09:36:43 +08:00
|
|
|
|
|
|
|
|
|
|
// 计算基于 dialogWidth 的位置参数 - 确保最小距离
|
2025-10-23 10:36:32 +08:00
|
|
|
|
const standardWidthVal = computed(() => {
|
2025-10-16 09:36:43 +08:00
|
|
|
|
return Math.max(0, 50)
|
2025-10-23 10:36:32 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const inputChannelXVal = computed(() => {
|
|
|
|
|
|
return Math.max(300, standardWidthVal.value + 300)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const outputChannelXVal = computed(() => {
|
|
|
|
|
|
return Math.max(600, prop.dialogWidth - 500)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const deviceWidthVal = computed(() => {
|
2025-10-16 09:36:43 +08:00
|
|
|
|
return Math.max(800, prop.dialogWidth - 350)
|
2025-10-23 10:36:32 +08:00
|
|
|
|
})
|
2025-10-16 09:36:43 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const createNodes = (device: Device.ResPqDev[], standardDev: StandardDevice.ResPqStandardDevice[], deviceMonitor: Map<string, any[]>) => {
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const channelCounts: Record<string, number> = {}
|
|
|
|
|
|
device.forEach(device => {
|
|
|
|
|
|
channelCounts[device.id] = device.devChns || 0
|
|
|
|
|
|
})
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const inspectionDevices = device.map(d => ({
|
|
|
|
|
|
id: d.id,
|
|
|
|
|
|
name: d.name,
|
|
|
|
|
|
type: 'normal',
|
2025-10-21 10:43:27 +08:00
|
|
|
|
deviceType: d.devType,
|
|
|
|
|
|
ip: d.ip,
|
|
|
|
|
|
monitorResults:d.monitorResults
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}))
|
|
|
|
|
|
|
2025-10-21 10:43:27 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
const channelCounts2: Record<string, number> = {}
|
|
|
|
|
|
standardDev.forEach(dev => {
|
|
|
|
|
|
const channelList = dev.inspectChannel ? dev.inspectChannel.split(',') : []
|
|
|
|
|
|
channelCounts2[dev.id] = channelList.length
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const standardDevices = standardDev.map(d => ({
|
|
|
|
|
|
id: d.id,
|
|
|
|
|
|
name: d.name,
|
|
|
|
|
|
type: 'normal',
|
2025-10-21 10:43:27 +08:00
|
|
|
|
deviceType: d.devType,
|
|
|
|
|
|
ip: d.ip
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
|
|
const newNodes: any[] = []
|
|
|
|
|
|
const deviceChannelGroups: { deviceId: string; centerY: number }[] = []
|
|
|
|
|
|
const standardChannelGroups: any[] = []
|
|
|
|
|
|
|
2025-10-16 09:36:43 +08:00
|
|
|
|
// const deviceWidth = 50
|
|
|
|
|
|
// const inputChannelX = 350
|
|
|
|
|
|
// const outputChannelX = 1050
|
|
|
|
|
|
// const standardWidth = 1170
|
2025-10-23 10:36:32 +08:00
|
|
|
|
const standardWidth = standardWidthVal.value
|
|
|
|
|
|
const outputChannelX = inputChannelXVal.value
|
|
|
|
|
|
const inputChannelX = outputChannelXVal.value
|
|
|
|
|
|
const deviceWidth = deviceWidthVal.value
|
2025-10-16 09:36:43 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
// 添加被检通道
|
2025-09-22 15:26:13 +08:00
|
|
|
|
// let currentYPosition = 50; // 初始Y位置
|
|
|
|
|
|
let actualChannelsTotalLength = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (const [deviceId, count] of Object.entries(channelCounts)) {
|
|
|
|
|
|
// 直接计算当前设备的通道数并累加,无需完整构建数组
|
|
|
|
|
|
actualChannelsTotalLength += deviceMonitor.has(deviceId)
|
|
|
|
|
|
? (deviceMonitor.get(deviceId) || []).length
|
|
|
|
|
|
: count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let currentYPosition = (vueFlowElement.value - 60 * actualChannelsTotalLength) / 2; // 初始Y位置
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const deviceSpacing = 30; // 设备间的垂直间距
|
2025-08-26 20:52:24 +08:00
|
|
|
|
Object.entries(channelCounts).forEach(([deviceId, count]) => {
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 从deviceMonitor中获取实际通道信息
|
|
|
|
|
|
let actualChannels = []; // 存储实际的通道号
|
2025-10-21 10:43:27 +08:00
|
|
|
|
let deviceMonitorResults: number[] = []; // 存储该设备的监控结果
|
|
|
|
|
|
// 获取该设备的monitorResults
|
|
|
|
|
|
const deviceInfo = inspectionDevices.find(d => d.id === deviceId);
|
|
|
|
|
|
if (deviceInfo && deviceInfo.monitorResults) {
|
|
|
|
|
|
deviceMonitorResults = deviceInfo.monitorResults;
|
|
|
|
|
|
}
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 如果deviceMonitor中有该设备的数据,则使用实际监测点信息
|
|
|
|
|
|
if (deviceMonitor.has(deviceId)) {
|
|
|
|
|
|
const monitorPoints = deviceMonitor.get(deviceId) || [];
|
|
|
|
|
|
// 提取监测点的num值作为通道号
|
|
|
|
|
|
actualChannels = monitorPoints.map(point => point.num);
|
|
|
|
|
|
//console.log('deviceId', deviceId, '实际通道号:', actualChannels, '监测点:', monitorPoints);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果没有monitor数据,默认使用连续的通道号
|
2025-09-22 15:26:13 +08:00
|
|
|
|
actualChannels = Array.from({ length: count }, (_, i) => i + 1);
|
2025-09-17 14:08:58 +08:00
|
|
|
|
}
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const yPosition = currentYPosition;
|
|
|
|
|
|
// 遍历实际通道号而不是连续的数字
|
|
|
|
|
|
actualChannels.forEach((channelNum, index) => {
|
|
|
|
|
|
const channelId = `被检通道-${deviceId}-${channelNum}`;
|
2025-10-21 10:43:27 +08:00
|
|
|
|
const channelResult = deviceMonitorResults[index]
|
|
|
|
|
|
|
|
|
|
|
|
let statusText = '';
|
|
|
|
|
|
if (channelResult === 0) {
|
|
|
|
|
|
statusText = '(不符合)';
|
|
|
|
|
|
} else if (channelResult === 1) {
|
|
|
|
|
|
statusText = '(符合)';
|
|
|
|
|
|
} else if (channelResult === 2) {
|
|
|
|
|
|
statusText = '(未检)';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
newNodes.push({
|
|
|
|
|
|
id: channelId,
|
|
|
|
|
|
type: 'input',
|
2025-10-21 10:43:27 +08:00
|
|
|
|
data: { label: createLabel3(`被检通道${channelNum}`+ statusText) },
|
2025-09-17 14:08:58 +08:00
|
|
|
|
position: { x: inputChannelX, y: yPosition + index * 50 },
|
2025-10-23 10:36:32 +08:00
|
|
|
|
sourcePosition: 'left',
|
2025-10-21 10:43:27 +08:00
|
|
|
|
style: { width: '160px', border: 'none', boxShadow: 'none' }
|
2025-09-17 14:08:58 +08:00
|
|
|
|
});
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-08 16:01:04 +08:00
|
|
|
|
deviceChannelGroups.push({
|
|
|
|
|
|
deviceId,
|
2025-09-22 15:26:13 +08:00
|
|
|
|
centerY: 0
|
2025-09-17 14:08:58 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 更新currentYPosition,为下一台设备留出空间
|
|
|
|
|
|
// 每台设备需要的空间 = 实际通道数 * 50 + 设备间距
|
|
|
|
|
|
currentYPosition += actualChannels.length * 50 + deviceSpacing;
|
|
|
|
|
|
});
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加标准通道
|
2025-09-22 15:26:13 +08:00
|
|
|
|
// let currentYPosition2 = 50; // 初始Y位置
|
|
|
|
|
|
let totalCount = 0;
|
|
|
|
|
|
// 遍历所有条目并累加 count 值
|
|
|
|
|
|
Object.entries(channelCounts2).forEach(([deviceId, count]) => {
|
|
|
|
|
|
totalCount += count;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let currentYPosition2 = (vueFlowElement.value - 60 * totalCount) / 2; // 初始Y位置; // 初始Y位置
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const standardDeviceSpacing = 30; // 标准设备间的垂直间距
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
Object.entries(channelCounts2).forEach(([deviceId, count]) => {
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const yPosition2 = currentYPosition2;
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
for (let i = 1; i <= count; i++) {
|
2025-09-17 14:08:58 +08:00
|
|
|
|
const channelId = `标准通道-${deviceId}-${i}`;
|
2025-08-26 20:52:24 +08:00
|
|
|
|
newNodes.push({
|
|
|
|
|
|
id: channelId,
|
|
|
|
|
|
type: 'output',
|
|
|
|
|
|
data: { label: createLabel3(`标准通道${i}`) },
|
2025-09-08 16:01:04 +08:00
|
|
|
|
position: { x: outputChannelX, y: yPosition2 + (i - 1) * 50 },
|
2025-10-23 10:36:32 +08:00
|
|
|
|
targetPosition: 'right',
|
2025-09-08 16:01:04 +08:00
|
|
|
|
style: { width: '120px', border: 'none', boxShadow: 'none' }
|
2025-09-17 14:08:58 +08:00
|
|
|
|
});
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
2025-09-08 16:01:04 +08:00
|
|
|
|
standardChannelGroups.push({
|
|
|
|
|
|
deviceId,
|
2025-09-17 14:08:58 +08:00
|
|
|
|
centerY: 0
|
|
|
|
|
|
});
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 更新currentYPosition2,为下一台标准设备留出空间
|
|
|
|
|
|
currentYPosition2 += count * 50 + standardDeviceSpacing;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加被检设备
|
|
|
|
|
|
// let deviceCurrentYPosition = 50; // 与通道计算保持一致的初始位置
|
2025-09-22 15:37:28 +08:00
|
|
|
|
let deviceCurrentYPosition = (vueFlowElement.value - 60 * actualChannelsTotalLength) / 2; // 与通道计算保持一致的初始位置
|
2025-09-17 14:08:58 +08:00
|
|
|
|
let lastDeviceId = ''; // 记录上一个处理的设备ID
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
|
|
|
|
|
deviceChannelGroups.forEach(({ deviceId, centerY }) => {
|
|
|
|
|
|
const device = inspectionDevices.find(d => d.id === deviceId)
|
|
|
|
|
|
if (device) {
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 只有当设备ID变化时才计算新位置
|
|
|
|
|
|
if (lastDeviceId !== deviceId) {
|
|
|
|
|
|
// 计算该设备对应的实际通道数量
|
|
|
|
|
|
let actualChannelCount = channelCounts[deviceId] || 0;
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 如果deviceMonitor中有该设备的数据,则使用实际监测点数量
|
|
|
|
|
|
if (deviceMonitor.has(deviceId)) {
|
|
|
|
|
|
const monitorPoints = deviceMonitor.get(deviceId) || [];
|
|
|
|
|
|
actualChannelCount = monitorPoints.length;
|
|
|
|
|
|
}
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 计算设备高度居中位置 - 基于该设备组的实际位置
|
|
|
|
|
|
const deviceCenterY = deviceCurrentYPosition + (actualChannelCount * 50) / 2 - 50
|
|
|
|
|
|
newNodes.push({
|
|
|
|
|
|
id: device.id,
|
2025-10-21 10:43:27 +08:00
|
|
|
|
data: { label: createLabel(device, 1) },
|
2025-09-17 14:08:58 +08:00
|
|
|
|
position: { x: deviceWidth, y: deviceCenterY },
|
|
|
|
|
|
class: 'no-handle-node',
|
|
|
|
|
|
style: { width: '300px', border: 'none', boxShadow: 'none' }
|
|
|
|
|
|
})
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 更新位置为下一台设备的起始位置
|
|
|
|
|
|
deviceCurrentYPosition += actualChannelCount * 50 + 30
|
|
|
|
|
|
// 更新上一个设备ID
|
|
|
|
|
|
lastDeviceId = deviceId
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
// 添加标准设备
|
2025-09-22 15:26:13 +08:00
|
|
|
|
// let standardDeviceCurrentYPosition = 50; // 与标准通道计算保持一致的初始位置
|
2025-09-22 15:37:28 +08:00
|
|
|
|
let standardDeviceCurrentYPosition = (vueFlowElement.value - 60 * totalCount) / 2; // 与标准通道计算保持一致的初始位置
|
2025-09-17 14:08:58 +08:00
|
|
|
|
let lastStandardDeviceId = ''; // 记录上一个处理的标准设备ID
|
|
|
|
|
|
|
2025-08-26 20:52:24 +08:00
|
|
|
|
standardChannelGroups.forEach(({ deviceId, centerY }) => {
|
|
|
|
|
|
const device = standardDevices.find(d => d.id === deviceId)
|
|
|
|
|
|
if (device) {
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 只有当设备ID变化时才计算新位置
|
|
|
|
|
|
if (lastStandardDeviceId !== deviceId) {
|
|
|
|
|
|
// 计算该标准设备对应的通道数量
|
|
|
|
|
|
const channelCount = channelCounts2[deviceId] || 0
|
|
|
|
|
|
// 计算设备高度居中位置 - 基于该设备组的实际位置
|
|
|
|
|
|
const deviceCenterY = standardDeviceCurrentYPosition + (channelCount * 50) / 2 - 50
|
|
|
|
|
|
newNodes.push({
|
|
|
|
|
|
id: device.id,
|
2025-10-21 10:43:27 +08:00
|
|
|
|
data: { label: createLabel(device, 2) },
|
2025-09-17 14:08:58 +08:00
|
|
|
|
position: { x: standardWidth, y: deviceCenterY },
|
|
|
|
|
|
class: 'no-handle-node',
|
|
|
|
|
|
style: { width: '300px', border: 'none', boxShadow: 'none' }
|
|
|
|
|
|
})
|
2025-09-22 15:26:13 +08:00
|
|
|
|
|
2025-09-17 14:08:58 +08:00
|
|
|
|
// 更新位置为下一台标准设备的起始位置
|
|
|
|
|
|
standardDeviceCurrentYPosition += channelCount * 50 + 30
|
|
|
|
|
|
// 更新上一个标准设备ID
|
|
|
|
|
|
lastStandardDeviceId = deviceId
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
//页面高度取决于设备通道
|
2025-09-08 16:01:04 +08:00
|
|
|
|
// dialogHeight.value = Math.max(yPosition.value, yPosition2.value)
|
2025-08-26 20:52:24 +08:00
|
|
|
|
|
|
|
|
|
|
return newNodes
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
defineExpose({ open, handleNext })
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
.flow-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vue-flow__node.no-handle-node .vue-flow__handle {
|
|
|
|
|
|
display: none !important;
|
|
|
|
|
|
}
|
2025-10-15 15:20:07 +08:00
|
|
|
|
|
|
|
|
|
|
/* 放大连线点 */
|
|
|
|
|
|
.vue-flow__handle {
|
|
|
|
|
|
width: 12px !important; /* 原来默认是 6px */
|
|
|
|
|
|
height: 12px !important; /* 原来默认是 6px */
|
|
|
|
|
|
background-color: #3b82f6 !important; /* 更明显的颜色 */
|
|
|
|
|
|
}
|
2025-08-26 20:52:24 +08:00
|
|
|
|
</style>
|