feat: 节点状态

This commit is contained in:
zhanghao 2026-04-14 17:22:08 +08:00
parent 88460d3bb1
commit 8c1820e1a6
11 changed files with 220 additions and 182 deletions

View File

@ -3,13 +3,16 @@
<div class="state__container" :class="`nodeState-${props.state}`"> <div class="state__container" :class="`nodeState-${props.state}`">
<div class="context"> <div class="context">
<div class="state"> <div class="state">
<el-icon> <el-icon>
<SuccessFilled v-if="props.state === 'SUCCESS'" /> <SuccessFilled v-if="props.state === 'SUCCESS'" />
<CircleCloseFilled v-if="['FAILED', 'STOPPED'].includes(props.state)" /> <CircleCloseFilled v-if="['FAILED', 'STOPPED'].includes(props.state)" />
<VideoPause v-if="props.state === 'PAUSED'" /> <VideoPause v-if="props.state === 'PAUSED'" />
<Loading v-if="props.state === 'RUNNING'" /> <Loading v-if="props.state === 'RUNNING'" />
</el-icon> </el-icon>
<div class="text">{{ getStateText() }}</div> <div class="text">{{ getStateText() }}</div>
<el-tag :type="props.state === 'SUCCESS' ? 'success' : 'danger'">
{{ props.runtimes }}ms
</el-tag>
</div> </div>
<div class="resultText" v-popover="popoverRef" @click="popoverVisible = !popoverVisible">{{ popoverVisible ? '隐藏结果' : '展示结果' }}</div> <div class="resultText" v-popover="popoverRef" @click="popoverVisible = !popoverVisible">{{ popoverVisible ? '隐藏结果' : '展示结果' }}</div>
</div> </div>
@ -49,6 +52,10 @@ const props = defineProps({
state: { state: {
type: String, type: String,
default: 'NORMAL' default: 'NORMAL'
},
runtimes: {
type: Number,
default: 0
} }
}) })

View File

@ -889,7 +889,7 @@
@visible-change=" @visible-change="
(visible) => visibleChange(visible, index, property.quote) (visible) => visibleChange(visible, index, property.quote)
" "
@change="(value) => cascaderChange(value, index)" @change="(value) => cascaderChange(value, index, 'httpBody')"
/> />
</el-form-item> </el-form-item>
</el-form-item> </el-form-item>
@ -955,6 +955,8 @@ const confirm = async () => {
ElMessage.error('JSON中存在错误请修正后再保存'); ElMessage.error('JSON中存在错误请修正后再保存');
return; return;
} }
} else {
} }
const nodeParams = [] const nodeParams = []
nodeParams.push({ name: "config", type: "input", input: "", children: httpNodeData.value.config, disabled: true, required: true }) nodeParams.push({ name: "config", type: "input", input: "", children: httpNodeData.value.config, disabled: true, required: true })
@ -1065,6 +1067,9 @@ const addFormItem = (e, type) => {
} else if (type === 'nodeParams' || type === 'outputParams') { } else if (type === 'nodeParams' || type === 'outputParams') {
obj.input = '' obj.input = ''
} }
if (!formData[type]) {
formData[type] = [];
}
formData[type].push(obj); formData[type].push(obj);
}; };
@ -1086,10 +1091,15 @@ const handleTypeChange = (index) => {
}; };
const cascaderRefs = ref([]); const cascaderRefs = ref([]);
const cascaderChange = (value, index) => { const cascaderChange = (value, index, type = 'default') => {
const selectedOptions = cascaderRefs.value[index].getCheckedNodes(true); const selectedOptions = cascaderRefs.value[index].getCheckedNodes(true);
formData.nodeParams[index].quote = value; if (type === 'default') {
formData.nodeParams[index].quoteType = selectedOptions[0].data.type; formData.nodeParams[index].quote = value;
formData.nodeParams[index].quoteType = selectedOptions[0].data.type;
} else {
formData.nodeParams.find(item => item.name === 'body').children.find(child => child.name === 'formData').children[index].quote = value;
formData.nodeParams.find(item => item.name === 'body').children.find(child => child.name === 'formData').children[index].quoteType = selectedOptions[0].data.type;
}
}; };
const visibleChange = (value, index, quote) => { const visibleChange = (value, index, quote) => {
@ -1240,8 +1250,14 @@ const httpNodeData = ref({
const addHttpNodeFormItem = (e, type) => { const addHttpNodeFormItem = (e, type) => {
e.stopPropagation(); e.stopPropagation();
if (type === 'body') { if (type === 'body') {
if (!httpNodeData.value.body.formData) {
httpNodeData.value.body.formData = [];
}
httpNodeData.value.body.formData.push({ name: "", type: "input", input: ""}); httpNodeData.value.body.formData.push({ name: "", type: "input", input: ""});
} else { } else {
if (!httpNodeData.value[type]) {
httpNodeData.value[type] = [];
}
httpNodeData.value[type].push({ name: "", type: "input", input: ""}); httpNodeData.value[type].push({ name: "", type: "input", input: ""});
} }
}; };

View File

@ -307,9 +307,7 @@ export const collapseList = [
{ name: "body", type: "input", input: "", children: [ { name: "body", type: "input", input: "", children: [
{ name: 'bodyType', type: "input", input: "json", disabled: true }, { name: 'bodyType', type: "input", input: "json", disabled: true },
{ name: 'json', type: "input", input: '{}' }, { name: 'json', type: "input", input: '{}' },
{ name: 'formData', type: "input", input: "", children: [ { name: 'formData', type: "input", input: "", children: []}
{ name: "", type: "input", input: ""}
]}
], required: true }, ], required: true },
], ],
outputType: 'json', outputType: 'json',

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -73,6 +73,7 @@ const setNodeName = (name) => {
} }
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
const errorInfoData = ref(''); const errorInfoData = ref('');
@ -82,6 +83,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
errorInfoData.value = data?.message || '' errorInfoData.value = data?.message || ''

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<keep-alive> <keep-alive>
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -23,9 +23,7 @@
</template> </template>
<script setup> <script setup>
import { watch, reactive, toRaw, ref, onMounted, onUnmounted, nextTick } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import { useFlowStore } from "@/store/modules/flow";
import { initNodeZoom } from "@/utils/flow";
import NodeState from "../../components/NodeState.vue"; import NodeState from "../../components/NodeState.vue";
import "vue3-json-viewer/dist/index.css"; import "vue3-json-viewer/dist/index.css";
import { emitter } from "@/utils/eventBus"; import { emitter } from "@/utils/eventBus";
@ -38,6 +36,7 @@ const emits = defineEmits(["contentChange"]);
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
@ -45,6 +44,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
try { try {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -69,6 +69,7 @@ const setNodeName = (name) => {
} }
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
const errorInfoData = ref(''); const errorInfoData = ref('');
@ -77,6 +78,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
errorInfoData.value = data?.message || '' errorInfoData.value = data?.message || ''

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -32,9 +32,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from "vue"; import { ref, reactive, onMounted, onUnmounted } from "vue";
import { getInput, initNodeZoom } from "@/utils/flow";
import { useFlowStore } from "@/store/modules/flow";
import NodeTitle from "../../components/NodeTitle.vue"; import NodeTitle from "../../components/NodeTitle.vue";
import NodeState from "../../components/NodeState.vue"; import NodeState from "../../components/NodeState.vue";
import "vue3-json-viewer/dist/index.css"; import "vue3-json-viewer/dist/index.css";
@ -64,6 +62,7 @@ const setNodeName = (name) => {
} }
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
@ -71,6 +70,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
try { try {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -48,7 +48,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, onUnmounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import NodeTitle from "../../components/NodeTitle.vue"; import NodeTitle from "../../components/NodeTitle.vue";
import NodeState from "../../components/NodeState.vue"; import NodeState from "../../components/NodeState.vue";
import "vue3-json-viewer/dist/index.css"; import "vue3-json-viewer/dist/index.css";
@ -72,6 +72,7 @@ const setNodeName = (name) => {
} }
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
const errorInfoData = ref(''); const errorInfoData = ref('');
@ -81,6 +82,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
errorInfoData.value = data?.message || '' errorInfoData.value = data?.message || ''

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" :class="props.model.id"> <div class="node__container" :class="props.model.id">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -33,9 +33,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick } from "vue"; import { ref, reactive, onMounted, onUnmounted } from "vue";
import { getInput, initNodeZoom } from "@/utils/flow";
import { useFlowStore } from "@/store/modules/flow";
import NodeTitle from "../../components/NodeTitle.vue"; import NodeTitle from "../../components/NodeTitle.vue";
import NodeState from "../../components/NodeState.vue"; import NodeState from "../../components/NodeState.vue";
import "vue3-json-viewer/dist/index.css"; import "vue3-json-viewer/dist/index.css";
@ -49,11 +47,6 @@ const props = defineProps({
const emits = defineEmits(["contentChange"]); const emits = defineEmits(["contentChange"]);
const formData = reactive({
nodeParams: [],
});
const setNodeName = (name) => { const setNodeName = (name) => {
const properties = lf.getProperties(props.model.id); const properties = lf.getProperties(props.model.id);
lf.setProperties(props.model.id, { lf.setProperties(props.model.id, {
@ -64,6 +57,7 @@ const setNodeName = (name) => {
} }
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
@ -71,6 +65,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
try { try {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="node__container" ref="switchRef" @mouseleave="setNodeProperties"> <div class="node__container" ref="switchRef" @mouseleave="setNodeProperties">
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus" :runtimes="runtimes">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
@ -385,6 +385,7 @@ const visibleChange = (value) => {
}; };
const nodeOperatingStatus = ref("NORMAL"); const nodeOperatingStatus = ref("NORMAL");
const runtimes = ref(0);
const inputJsonData = ref({}); const inputJsonData = ref({});
const outputJsonData = ref({}); const outputJsonData = ref({});
const errorInfoData = ref(''); const errorInfoData = ref('');
@ -414,6 +415,9 @@ onMounted(() => {
emitter.on("changeNodeState", (data) => { emitter.on("changeNodeState", (data) => {
if (data.nodeId === props.model.id) { if (data.nodeId === props.model.id) {
nodeOperatingStatus.value = data.status; nodeOperatingStatus.value = data.status;
if (data.endTime && data.startTime) {
runtimes.value = data.endTime - data.startTime;
}
let inputData = {}; let inputData = {};
let output = {}; let output = {};
errorInfoData.value = data?.message || '' errorInfoData.value = data?.message || ''

View File

@ -47,11 +47,11 @@ export default defineConfig(({mode, command}) => {
proxy: { proxy: {
// https://cn.vitejs.dev/config/#server-proxy // https://cn.vitejs.dev/config/#server-proxy
'/dev-api': { '/dev-api': {
//杨 http://192.168.0.10:13080 //服务器 http://192.168.0.100:13080
//赵 http://10.148.108.58:13080 //李小龙 http://192.168.0.5:13080
// dev http://10.148.20.34:13080 // dev http://10.148.20.34:13080
// target: VITE_API_URL, // target: VITE_API_URL,
target: command === 'build' ? VITE_API_URL : 'http://192.168.0.100:13080', target: command === 'build' ? VITE_API_URL : 'http://192.168.0.5:13080',
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '') rewrite: (p) => p.replace(/^\/dev-api/, '')
} }