forked from SmartBench/CMVR-IOT-UI
- 增加了检测流资源中引用循环的功能,以防止循环依赖。 - 改进了流引用的验证,以确保节点输出中不存在循环依赖。 - 增强了资源定义清理功能,以便在执行前移除过时的设备ID。 - 已实现复制资源角色的合并,以优化现有资源的优先级并避免重复。 - 更新了LoopIterationResults组件,以管理运行中迭代的自动扩展。 - 增强了NodeState和NodeTitle组件,以支持循环和子流结果的更宽弹出框显示。 - 优化了ParamsDrawer和SubFlowExecutionResults组件,以处理动态参数更新和执行结果。 - 改进了TaskExecutionLog,以统一输出处理并增强用户对日志的可见性。 - 更新了各种参数组件,以简化输入处理并提升用户体验。 - 在代码中添加了全面的注释和文档,以提高可维护性和易理解性。
101 lines
3.6 KiB
Vue
101 lines
3.6 KiB
Vue
<template>
|
||
<div class="node__container" :class="props.model.id">
|
||
<NodeState
|
||
ref="nodeStateRef"
|
||
:state="nodeOperatingStatus"
|
||
:runtimes="runtimes"
|
||
:popover-width="760"
|
||
popper-class="flow-result-popover flow-subflow-result-popover"
|
||
>
|
||
<template #input>
|
||
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
|
||
</template>
|
||
<template #output>
|
||
<SubFlowExecutionResults v-if="nodeOperatingStatus !== 'FAILED'" :data="subFlowExecution" />
|
||
<div v-else class="subflow-error">{{ errorInfoData }}</div>
|
||
</template>
|
||
</NodeState>
|
||
<NodeTitle
|
||
:icon="props.properties.icon"
|
||
:node-id="props.model.id"
|
||
:node-properties="props.properties"
|
||
:node-type="props.properties.nodeType || 'NONE'"
|
||
:node-name="props.properties.name"
|
||
:node-desc="props.properties.desc"
|
||
@set-node-name="setNodeName"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, onMounted, ref } from 'vue'
|
||
import NodeState from '../../components/NodeState.vue'
|
||
import NodeTitle from '../../components/NodeTitle.vue'
|
||
import SubFlowExecutionResults from '../../components/SubFlowExecutionResults.vue'
|
||
import { useFlowEvents } from '../../composables/useFlowEvents'
|
||
|
||
const props = defineProps({ model: Object, properties: Object })
|
||
const emits = defineEmits(['contentChange'])
|
||
const { onFlowEvent } = useFlowEvents()
|
||
const nodeStateRef = ref(null)
|
||
const nodeOperatingStatus = ref('NORMAL')
|
||
const runtimes = ref(0)
|
||
const inputJsonData = ref({})
|
||
const outputJsonData = ref({})
|
||
const errorInfoData = ref('')
|
||
// 优先使用主页面轮询聚合出的 subFlowExecution;没有内部日志时退回到普通输出,保证旧数据仍可展示。
|
||
const subFlowExecution = computed(() => outputJsonData.value?.subFlowExecution || {
|
||
name: props.properties?.subFlow?.detectName || props.properties?.name,
|
||
versionNo: props.properties?.subFlow?.versionNo,
|
||
output: outputJsonData.value,
|
||
executions: [],
|
||
})
|
||
|
||
// 子流程输出来自后端运行日志,兼容 JSON 字符串和对象;解析失败时保留原值用于排查。
|
||
const parseValue = (value) => {
|
||
if (!value) return {}
|
||
if (typeof value === 'object') return value
|
||
try { return JSON.parse(value) || {} } catch { return value }
|
||
}
|
||
|
||
const setNodeName = (name) => {
|
||
const properties = lf.getProperties(props.model.id)
|
||
lf.setProperties(props.model.id, { ...properties, name })
|
||
emits('contentChange')
|
||
}
|
||
|
||
onMounted(() => {
|
||
onFlowEvent('changeNodeState', (data) => {
|
||
if (data.nodeId !== props.model.id) return
|
||
// 外层子流程节点状态由主页面统一聚合内部日志后派发,这里只负责同步到节点 UI。
|
||
nodeOperatingStatus.value = data.status
|
||
runtimes.value = data.endTime && data.startTime ? data.endTime - data.startTime : 0
|
||
inputJsonData.value = parseValue(data.paramsIn)
|
||
outputJsonData.value = parseValue(data.paramsOut)
|
||
errorInfoData.value = data?.message || ''
|
||
emits('contentChange')
|
||
})
|
||
onFlowEvent('contentChange', (data) => {
|
||
if (data.id !== props.model.id) return
|
||
nodeOperatingStatus.value = 'NORMAL'
|
||
inputJsonData.value = {}
|
||
outputJsonData.value = {}
|
||
emits('contentChange')
|
||
})
|
||
})
|
||
|
||
defineExpose({ closePopover: () => nodeStateRef.value?.closePopover?.() })
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.node__container { width: 100%; height: auto; }
|
||
.subflow-error { color: var(--el-color-danger); line-height: 20px; overflow-wrap: anywhere; }
|
||
</style>
|
||
|
||
<style lang="scss">
|
||
.flow-subflow-result-popover {
|
||
max-width: min(760px, calc(100vw - 32px));
|
||
.result-section__content { max-height: 560px; }
|
||
}
|
||
</style>
|