feat: 新增节点

This commit is contained in:
zhanghao 2025-09-22 15:42:11 +08:00
parent e988f6a183
commit ec2d020ae8
9 changed files with 454 additions and 404 deletions

View File

@ -12,6 +12,10 @@ import startSvg from './icon/start.svg'
import endSvg from './icon/end.svg' import endSvg from './icon/end.svg'
import microphoneSvg from './icon/microphone.svg' import microphoneSvg from './icon/microphone.svg'
import sleepSvg from './icon/sleep.svg' import sleepSvg from './icon/sleep.svg'
import planSvg from './icon/plan.svg'
import awakenSvg from './icon/awaken.svg'
import dialogueSvg from './icon/dialogue.svg'
import audioSvg from './icon/audio.svg'
import { v4 as randomUUID } from 'uuid' import { v4 as randomUUID } from 'uuid'
@ -106,7 +110,7 @@ export const collapseList = [
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true }
], ],
outputType: 'img', outputType: 'img',
outputParams: [{ name: 'imageUrl', type: 'array<string>', desc: '图片地址数组', disabled: true}] outputParams: [{ name: 'imageUrl', type: 'array<string>', desc: '图片地址数组', children: [], disabled: true }]
}, },
{ {
icon: cameraSvg, icon: cameraSvg,
@ -145,7 +149,7 @@ export const collapseList = [
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true } { name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true }
], ],
outputType: 'video', outputType: 'video',
outputParams: [{ name: 'videoUrl', type: 'array<string>', desc: '视频播放地址数组'}] outputParams: [{ name: 'videoUrl', type: 'array<string>', children: [], desc: '视频播放地址数组'}]
} }
], ],
}, },
@ -242,7 +246,7 @@ export const collapseList = [
outputType: 'json' outputType: 'json'
}, },
{ {
icon: microphoneSvg, icon: audioSvg,
name: "播放音频", name: "播放音频",
type: "serviceNode", type: "serviceNode",
desc: "用于播放音频的节点", desc: "用于播放音频的节点",
@ -269,7 +273,7 @@ export const collapseList = [
{ name: "vehType", type: "input", input: "su7", disabled: true }, { name: "vehType", type: "input", input: "su7", disabled: true },
], ],
outputType: 'json', outputType: 'json',
outputParams: [{ name: 'coordinates', type: 'Object', desc: '坐标对象'}] outputParams: [{ name: 'coordinates', type: 'Object', children: [], desc: '坐标对象'}]
}, },
], ],
}, },
@ -277,17 +281,60 @@ export const collapseList = [
collapseTitle: "语音交互", collapseTitle: "语音交互",
nodeList: [ nodeList: [
{ {
icon: microphoneSvg, icon: planSvg,
name: "方案处理",
type: "serviceNode",
desc: "语音交互-方案处理",
action: 'VI_SCHEME',
nodeParams: [{ name: 'schemeId', type: "input", input: "", disabled: true }],
outputType: 'json',
outputParams: [
{ name: 'wakeCorpus', type: 'object', desc: '唤醒语料', children: [], disabled: true},
{ name: 'testCorpus', type: 'array<object>', desc: '测试语料数组', children: [], disabled: true}
]
},
{
icon: awakenSvg,
name: "唤醒语料", name: "唤醒语料",
type: "serviceNode", type: "serviceNode",
desc: "唤醒语料处理", desc: "唤醒语料处理",
action: 'VI_WAKE_CORPUS', action: 'VI_CORPUS_WAKE',
nodeParams: [
{ name: "", type: "input", input: ""}
],
outputType: 'json', outputType: 'json',
outputParams: [{ name: 'coordinates', type: 'Object', desc: '坐标对象'}] nodeParams: [{ name: 'wakeCorpus', type: "input", input: "", disabled: true }],
outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}]
}, },
{
icon: dialogueSvg,
name: "单次对话语料",
type: "serviceNode",
desc: "测试语料-单次对话语料处理",
action: 'VI_CORPUS_WAKE',
outputType: 'json',
nodeParams: [{ name: 'testCorpus', type: "input", input: "", disabled: true }],
outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}]
},
{
icon: dialogueSvg,
name: "连续对话语料",
type: "serviceNode",
desc: "测试语料-连续对话语料处理",
action: 'VI_CORPUS_CONTINUOUS',
outputType: 'json',
nodeParams: [{ name: 'testCorpus', type: "input", input: "", disabled: true }],
outputParams: [{ name: 'audioPath', type: 'string', desc: '语音路径', disabled: true}]
},
{
icon: audioSvg,
name: "播放语料",
type: "serviceNode",
desc: "用于播放语料的节点",
action: 'VI_PLAY_CORPUS',
outputType: 'json',
nodeParams: [
{ name: 'audioPath', type: "input", input: "", disabled: true },
{ name: 'deviceId', type: "input", input: "", disabled: true },
],
}
], ],
}, },
] ]

View File

@ -0,0 +1 @@
<svg t="1758526814700" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11094" width="200" height="200"><path d="M983.779623 312.719408a510.292483 510.292483 0 0 0-109.795373-162.701951A511.088926 511.088926 0 0 0 512.000853 0.001707a508.756485 508.756485 0 0 0-361.983396 150.01575A511.088926 511.088926 0 0 0 0.001707 512.000853a508.756485 508.756485 0 0 0 150.01575 361.983397 511.088926 511.088926 0 0 0 162.701951 109.738484c63.089673 26.680844 130.161561 40.163489 199.281445 40.163488a508.756485 508.756485 0 0 0 199.281446-40.163488 508.358264 508.358264 0 0 0 162.701951-109.738484 511.088926 511.088926 0 0 0 109.738484-162.701951c26.680844-63.089673 40.163489-130.161561 40.163488-199.281446a508.642708 508.642708 0 0 0-40.106599-199.281445z m-55.295908 375.181597a451.583247 451.583247 0 0 1-96.881617 143.701093 451.583247 451.583247 0 0 1-143.701093 96.881617c-55.751018 23.60885-114.915364 35.498608-175.900152 35.498607a448.397475 448.397475 0 0 1-175.900151-35.498607 451.583247 451.583247 0 0 1-143.701094-96.881617 451.583247 451.583247 0 0 1-96.881616-143.701093A448.397475 448.397475 0 0 1 60.019384 512.000853c0-60.984787 11.889758-120.206022 35.498608-175.900151 22.755518-53.816799 55.409685-102.172274 96.881616-143.701094a451.583247 451.583247 0 0 1 143.701094-96.881616A448.397475 448.397475 0 0 1 512.000853 60.019384c60.984787 0 120.206022 11.889758 175.900152 35.498608 53.816799 22.755518 102.172274 55.409685 143.701093 96.881616 41.52882 41.52882 74.126099 89.884295 96.881617 143.701094 23.60885 55.751018 35.498608 114.915364 35.498607 175.900151s-11.889758 120.206022-35.498607 175.900152z" fill="#65BEE0" p-id="11095"></path><path d="M263.965711 416.029458a30.094172 30.094172 0 0 0-29.980394 29.980394v131.982002a30.094172 30.094172 0 0 0 60.017677 0V446.009852a30.094172 30.094172 0 0 0-29.980394-29.980394z m124.017571-63.999894a30.094172 30.094172 0 0 0-29.980394 29.980395v259.981789c0 16.49775 13.482644 29.980394 29.980394 29.980394 16.49775 0 30.037283-13.482644 30.037284-29.980394v-259.981789a30.094172 30.094172 0 0 0-30.037284-29.980395zM512.000853 256.00128a30.094172 30.094172 0 0 0-29.980394 29.980394v452.038358c0 16.49775 13.482644 29.980394 29.980394 29.980395 16.49775 0 29.980394-13.482644 29.980395-29.980395V285.981674A30.094172 30.094172 0 0 0 512.000853 256.00128z m248.035142 160.028178a30.094172 30.094172 0 0 0-30.037283 29.980394v131.982002c0 16.49775 13.482644 29.980394 29.980395 29.980395 16.49775 0 30.037283-13.482644 30.037283-29.980395V446.009852a30.094172 30.094172 0 0 0-30.037283-29.980394z m-124.017571-63.999894a30.094172 30.094172 0 0 0-30.037283 29.980395v259.981789a30.094172 30.094172 0 0 0 60.017678 0v-259.981789a30.094172 30.094172 0 0 0-29.980395-29.980395z" fill="#65BEE0" p-id="11096"></path></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1 @@
<svg t="1758526221559" class="icon" viewBox="0 0 1142 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3938" width="200" height="200"><path d="M477.13739 76.859452c-260.63725 0-471.90562 211.26837-471.90562 471.90562 0 260.542127 211.26837 471.90562 471.90562 471.90562 260.63725 0 471.90562-211.26837 471.90562-471.90562C948.947887 288.127822 737.77464 76.859452 477.13739 76.859452zM477.13739 874.08602c-37.00288 0-67.156897-29.393033-67.156897-65.349559 0-4.661031 3.614677-8.370831 8.085462-8.370831l118.047747 0c4.470785 0 8.085462 3.7098 8.085462 8.370831C544.294287 844.692987 514.140269 874.08602 477.13739 874.08602zM696.966837 750.235764 254.834742 750.235764c-3.424431 0-6.278124-2.853693-6.278124-6.46837l0-47.085927c0-28.441802 32.532095-50.985973 75.337483-53.459173-5.23177-15.505063-7.895216-31.485741-7.895216-47.751788L315.998885 464.676266c0-66.776405 43.281003-124.991732 108.154947-146.394426L424.153832 304.964608c0-27.775941 23.210033-50.320111 51.746958-50.320111 28.536925 0 51.746958 22.544171 51.746958 50.320111l0 13.222109c64.873943 21.402694 108.154947 79.618021 108.154947 146.394426l0 130.889364c0 16.170924-2.663446 32.151602-7.990339 47.751788 42.805388 2.4732 75.337483 25.017371 75.337483 53.459173l0 47.085927C703.244961 747.382072 700.486391 750.235764 696.966837 750.235764z" p-id="3939" fill="#65BEE0"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg t="1758526744847" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8113" width="200" height="200"><path d="M512 117.76c218.065455 0 395.636364 135.68 395.636364 302.545455s-177.570909 302.545455-395.636364 302.545454a144.058182 144.058182 0 0 0-50.501818 10.472727 791.272727 791.272727 0 0 0-162.909091 99.374546c-4.421818-128.232727-23.272727-168.96-56.087273-191.534546C162.909091 584.145455 116.363636 503.621818 116.363636 420.538182c0-167.098182 177.570909-302.545455 395.636364-302.545455m0-69.818182c-256 0-465.454545 166.632727-465.454545 372.363637 0 110.312727 59.810909 209.454545 155.22909 277.643636 23.272727 16.756364 27.694545 116.363636 27.694546 192.232727a41.192727 41.192727 0 0 0 40.494545 41.89091 40.029091 40.029091 0 0 0 23.272728-8.61091c58.414545-45.149091 141.730909-105.425455 192-124.50909a74.007273 74.007273 0 0 1 26.763636-6.05091c256 0 465.454545-166.865455 465.454545-372.363636s-209.454545-372.363636-465.454545-372.363636z" fill="#65BEE0" p-id="8114"></path><path d="M663.272727 325.818182h-302.545454a34.909091 34.909091 0 0 0 0 69.818182h302.545454a34.909091 34.909091 0 0 0 0-69.818182zM616.727273 488.727273h-209.454546a34.909091 34.909091 0 0 0 0 69.818182h209.454546a34.909091 34.909091 0 0 0 0-69.818182z" fill="#65BEE0" p-id="8115"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg t="1758526128932" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2666" width="200" height="200"><path d="M512 575.146667c-10.922667 0-21.845333-2.730667-31.402667-8.192L352.426667 494.933333l-48.810667 27.477334L512 639.658667l208.384-117.248L671.573333 494.933333l-128.170666 72.192c-9.557333 5.290667-20.48 8.021333-31.402667 8.021334z" fill="#65BEE0" p-id="2667"></path><path d="M512 708.437333c-10.922667 0-21.845333-2.730667-31.402667-8.192l-146.432-82.432-30.378666 17.237334L512 752.128l208.384-117.248-30.378667-17.237333-146.432 82.432c-9.728 5.632-20.650667 8.362667-31.573333 8.362666z" fill="#65BEE0" p-id="2668"></path><path d="M512 34.133333C248.149333 34.133333 34.133333 248.149333 34.133333 512s214.016 477.866667 477.866667 477.866667 477.866667-214.016 477.866667-477.866667S775.850667 34.133333 512 34.133333z m248.149333 432.128c20.138667 11.434667 32.768 32.768 32.768 55.978667 0 23.210667-12.458667 44.544-32.597333 55.978667l-0.853333 0.341333 0.682666 0.341333c20.138667 11.264 32.768 32.768 32.768 55.808 0 23.210667-12.458667 44.544-32.768 55.978667l-216.746666 122.026667a64.529067 64.529067 0 0 1-62.976 0l-216.746667-122.026667a64.494933 64.494933 0 0 1-32.768-55.978667c0-23.210667 12.629333-44.544 32.768-55.978666l0.682667-0.341334-0.682667-0.341333a64.494933 64.494933 0 0 1-32.768-55.978667c0-23.210667 12.629333-44.544 32.768-55.978666l18.944-10.581334-18.944-10.752a64.494933 64.494933 0 0 1-32.768-55.978666c0-23.210667 12.458667-44.544 32.768-55.978667l216.746667-122.026667c19.456-10.922667 43.52-10.922667 62.976 0l216.746666 122.026667c20.138667 11.434667 32.768 32.768 32.768 55.978667 0 23.210667-12.629333 44.544-32.768 55.978666l-18.944 10.752 18.944 10.752z" fill="#65BEE0" p-id="2669"></path><path d="M720.384 389.12L512 271.701333 303.616 389.12 512 506.368z" fill="#65BEE0" p-id="2670"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -11,7 +11,7 @@
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
> >
<el-input <el-input
:disabled="isFirstLevel && index === 0" :disabled="item.disabled"
v-model="item.name" v-model="item.name"
placeholder="请输入" placeholder="请输入"
clearable clearable
@ -25,7 +25,7 @@
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
> >
<el-select <el-select
:disabled="isFirstLevel && index === 0" :disabled="item.disabled"
v-model="item.type" v-model="item.type"
@change="handleTypeChange(item)" @change="handleTypeChange(item)"
> >
@ -47,7 +47,7 @@
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
> >
<el-input <el-input
:disabled="isFirstLevel && index === 0" :disabled="item.disabled"
v-model="item.desc" v-model="item.desc"
placeholder="请输入" placeholder="请输入"
clearable clearable
@ -55,16 +55,16 @@
</el-form-item> </el-form-item>
<!-- 是否必填 --> <!-- 是否必填 -->
<el-form-item :label="isFirstLevel && index === 0 ? '必填' : ''"> <el-form-item v-if="formType === 'input'" :label="isFirstLevel && index === 0 ? '必填' : ''">
<el-switch <el-switch
:disabled="isFirstLevel && index === 0" :disabled="item.disabled"
v-model="item.required" v-model="item.required"
/> />
</el-form-item> </el-form-item>
<!-- 删除按钮第一层第一个不能删 --> <!-- 删除按钮第一层第一个不能删 -->
<el-button <el-button
v-if="!(isFirstLevel && index === 0)" v-if="!item?.disabled"
:icon="Minus" :icon="Minus"
circle circle
size="small" size="small"
@ -94,6 +94,7 @@
<!-- 非第一层 --> <!-- 非第一层 -->
<!-- 复用添加逻辑 --> <!-- 复用添加逻辑 -->
<FormItemRecursive <FormItemRecursive
:formType="formType"
:current-list="item.children" :current-list="item.children"
:prop-path="`${propPath}.${index}.children`" :prop-path="`${propPath}.${index}.children`"
:depth="depth + 1" :depth="depth + 1"
@ -112,7 +113,11 @@
import { Plus, Minus } from "@element-plus/icons-vue"; import { Plus, Minus } from "@element-plus/icons-vue";
// props // props
const { currentList, propPath, depth, isFirstLevel, endDepth, parentPath } = defineProps({ const { formType, currentList, propPath, depth, isFirstLevel, endDepth, parentPath } = defineProps({
formType: {
type: String,
default: 'input'
},
currentList: { currentList: {
type: Array, type: Array,
default: () => [] default: () => []

View File

@ -131,18 +131,8 @@
:rules="outputRules" :rules="outputRules"
ref="outputFormRef" ref="outputFormRef"
> >
<!-- <el-row v-for="(item, index) in formData.outputParams">
<el-form-item :label="index === 0 ? '参数名' : ''" >
<el-input :value="item.name" :disabled="item?.disabled" />
</el-form-item>
<el-form-item :label="index === 0 ? '参数类型' : ''" >
<el-input :value="item.type" />
</el-form-item>
<el-form-item :label="index === 0 ? '描述' : ''">
<el-input :value="item.desc" />
</el-form-item>
</el-row> -->
<FormItemRecursive <FormItemRecursive
formType="output"
:current-list="formData.outputParams" :current-list="formData.outputParams"
prop-path="outputParams" prop-path="outputParams"
:depth="0" :depth="0"
@ -192,7 +182,6 @@ const handleTypeChange = (index) => {
} else { } else {
formData.nodeParams[index].input = ""; formData.nodeParams[index].input = "";
const option = getInput(props.model.id); const option = getInput(props.model.id);
console.log('option', option)
if (option) { if (option) {
quoteOptions.value = option; quoteOptions.value = option;
} }
@ -203,6 +192,7 @@ const cascaderRefs = ref([])
const outputRules = reactive({}); const outputRules = reactive({});
const cascaderChange = (value, index) => { const cascaderChange = (value, index) => {
const selectedOptions = cascaderRefs.value[index].getCheckedNodes(true); const selectedOptions = cascaderRefs.value[index].getCheckedNodes(true);
formData.nodeParams[index].quote = value
formData.nodeParams[index].quoteType = selectedOptions[0].data.type formData.nodeParams[index].quoteType = selectedOptions[0].data.type
} }
@ -220,10 +210,12 @@ const outputFormRef = ref()
const setNodeProperties = async () => { const setNodeProperties = async () => {
try { try {
const result = await dynamicForm.value.validate(); const result = await dynamicForm.value.validate();
console.log(123456) let flag = true
const test = await outputFormRef.value.validate() if (outputFormRef.value) {
console.log('test', test) flag = await outputFormRef.value.validate()
if (result) { }
if (result && flag) {
const data = toRaw(formData); const data = toRaw(formData);
console.log('data', data) console.log('data', data)
const properties = lf.getProperties(props.model.id); const properties = lf.getProperties(props.model.id);
@ -492,15 +484,15 @@ defineExpose({
align-items: end; align-items: end;
.el-input { .el-input {
--el-input-width: 120px; --el-input-width: 148px;
} }
.el-select { .el-select {
--el-select-width: 120px; --el-select-width: 148px;
} }
.el-cascader { .el-cascader {
--el-form-inline-content-width: 120px; --el-form-inline-content-width: 148px;
} }
} }
} }

View File

@ -1,367 +1,369 @@
<template> <template>
<div class="node__container"> <div class="node__container">
<keep-alive> <keep-alive>
<NodeState :state="nodeOperatingStatus"> <NodeState :state="nodeOperatingStatus">
<template #input> <template #input>
<JsonViewer :value="inputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="inputJsonData" copyable boxed sort theme="light" />
</template> </template>
<!-- <template #output> <!-- <template #output>
<JsonViewer :value="outputJsonData" copyable boxed sort theme="light" /> <JsonViewer :value="outputJsonData" copyable boxed sort theme="light" />
</template> --> </template> -->
</NodeState> </NodeState>
</keep-alive> </keep-alive>
<div class="title__container"> <div class="title__container">
<div class="title"> <div class="title">
<img src="../../icon/start.svg" alt="" /> <img src="../../icon/start.svg" alt="" />
<span class="text">Start</span> <span class="text">Start</span>
</div> </div>
<div class="subTitle">工作流的起始节点用于设定启动工作流需要的信息</div> <div class="subTitle">工作流的起始节点用于设定启动工作流需要的信息</div>
</div> </div>
<div class="input__container"> <div class="input__container">
<div class="title"> <div class="title">
<div class="left"> <div class="left">
<div class="tag"></div> <div class="tag"></div>
<div class="text">输入</div> <div class="text">输入</div>
</div> </div>
<div class="right"> <div class="right">
<el-button <el-button
:disabled="flowStore.disableForm" :disabled="flowStore.disableForm"
@click="addFormItem" @click="addFormItem"
class="addFormItem" class="addFormItem"
> >
<el-icon :size="20"><Plus /></el-icon> <el-icon :size="20"><Plus /></el-icon>
</el-button> </el-button>
</div> </div>
</div> </div>
<div class="form__container"> <div class="form__container">
<el-form <el-form
:inline="true" :inline="true"
:model="formData" :model="formData"
:rules="rules" :rules="rules"
ref="dynamicForm" ref="dynamicForm"
label-position="top" label-position="top"
label-width="auto" label-width="auto"
:disabled="flowStore.disableForm" :disabled="flowStore.disableForm"
> >
<FormItemRecursive <FormItemRecursive
:current-list="formData.inputParams" formType="input"
prop-path="inputParams" :current-list="formData.inputParams"
:depth="0" prop-path="inputParams"
:is-first-level="true" :depth="0"
:endDepth="2" :is-first-level="true"
:parent-path="[]" :endDepth="2"
@delete-item="deleteTopLevelItem" :parent-path="[]"
/> @delete-item="deleteTopLevelItem"
</el-form> />
</div> </el-form>
</div> </div>
</div> </div>
</template> </div>
</template>
<script setup>
import { watch, reactive, toRaw, ref, onMounted, onUnmounted } from "vue"; <script setup>
import { Plus } from "@element-plus/icons-vue"; import { watch, reactive, toRaw, ref, onMounted, onUnmounted } from "vue";
import { useFlowStore } from "@/store/modules/flow"; import { Plus } from "@element-plus/icons-vue";
import NodeState from "../../components/NodeState.vue"; import { useFlowStore } from "@/store/modules/flow";
import "vue3-json-viewer/dist/index.css"; import NodeState from "../../components/NodeState.vue";
import { emitter } from "@/utils/eventBus"; import "vue3-json-viewer/dist/index.css";
import FormItemRecursive from "./FormItemRecursive.vue"; import { emitter } from "@/utils/eventBus";
import FormItemRecursive from "./FormItemRecursive.vue";
const props = defineProps({
model: Object, const props = defineProps({
properties: Object, model: Object,
}); properties: Object,
const emits = defineEmits(["contentChange"]); });
const emits = defineEmits(["contentChange"]);
const flowStore = useFlowStore();
const flowStore = useFlowStore();
const formData = reactive({
inputParams: [ const formData = reactive({
{ inputParams: [
name: "terminalId", {
type: "string", name: "terminalId",
desc: "机器人ip", type: "string",
required: true, desc: "机器人ip",
children: [], disabled: true,
}, required: true,
], children: [],
}); },
],
const rules = reactive({}); });
const addFormItem = () => { const rules = reactive({});
formData.inputParams.push({
name: "", const addFormItem = () => {
type: "", formData.inputParams.push({
desc: "", name: "",
required: false, type: "",
children: [], desc: "",
}); required: false,
emits("contentChange"); children: [],
}; });
emits("contentChange");
const dynamicForm = ref(); };
const setNodeProperties = async () => { const dynamicForm = ref();
try {
const result = await dynamicForm.value.validate(); const setNodeProperties = async () => {
if (result) { try {
const data = toRaw(formData); const result = await dynamicForm.value.validate();
lf.setProperties(props.model.id, { if (result) {
...props.properties, const data = toRaw(formData);
...data, lf.setProperties(props.model.id, {
}); ...props.properties,
emits("contentChange"); ...data,
} });
} catch { emits("contentChange");
dynamicForm.value.clearValidate() }
} } catch {
}; dynamicForm.value.clearValidate()
}
const nodeOperatingStatus = ref("NORMAL"); };
const inputJsonData = ref({});
const outputJsonData = ref({}); const nodeOperatingStatus = ref("NORMAL");
const inputJsonData = ref({});
watch( const outputJsonData = ref({});
() => props.properties,
() => { watch(
if (props.properties.inputParams && props.properties.inputParams.length > 0) { () => props.properties,
formData.inputParams = props.properties.inputParams; () => {
} if (props.properties.inputParams && props.properties.inputParams.length > 0) {
}, formData.inputParams = props.properties.inputParams;
{ }
immediate: true, },
deep: true, {
} immediate: true,
); deep: true,
}
// );
const deleteTopLevelItem = (fullPath) => {
// //
let currentLevel = formData.inputParams; const deleteTopLevelItem = (fullPath) => {
//
// let currentLevel = formData.inputParams;
for (let i = 0; i < fullPath.length - 1; i++) {
const index = fullPath[i]; //
// for (let i = 0; i < fullPath.length - 1; i++) {
currentLevel = currentLevel[index].children; const index = fullPath[i];
} //
currentLevel = currentLevel[index].children;
// }
const lastIndex = fullPath[fullPath.length - 1];
currentLevel.splice(lastIndex, 1); //
emits("contentChange"); const lastIndex = fullPath[fullPath.length - 1];
} currentLevel.splice(lastIndex, 1);
emits("contentChange");
onMounted(() => { }
setNodeProperties();
emitter.on("changeNodeState", (data) => { onMounted(() => {
if (data.nodeId === props.model.id) { setNodeProperties();
nodeOperatingStatus.value = data.status; emitter.on("changeNodeState", (data) => {
let inputData = {}; if (data.nodeId === props.model.id) {
let output = {}; nodeOperatingStatus.value = data.status;
try { let inputData = {};
inputData = JSON.parse(data.paramsIn) || {}; let output = {};
output = JSON.parse(data.paramsOut) || {}; try {
} catch (error) { inputData = JSON.parse(data.paramsIn) || {};
inputData = data.paramsIn || {}; output = JSON.parse(data.paramsOut) || {};
output = data.paramsOut || {}; } catch (error) {
} inputData = data.paramsIn || {};
inputJsonData.value = inputData; output = data.paramsOut || {};
outputJsonData.value = output; }
inputJsonData.value = inputData;
emits("contentChange"); outputJsonData.value = output;
}
}); emits("contentChange");
}
emitter.on("contentChange", (data) => { });
if (data.id === props.model.id) {
nodeOperatingStatus.value = "NORMAL"; emitter.on("contentChange", (data) => {
inputJsonData.value = {}; if (data.id === props.model.id) {
outputJsonData.value = {}; nodeOperatingStatus.value = "NORMAL";
inputJsonData.value = {};
emits("contentChange"); outputJsonData.value = {};
}
}); emits("contentChange");
}); }
});
const validateForm = async () => { });
try {
const result = await dynamicForm.value.validate(); const validateForm = async () => {
if (result) { try {
return { valid: true, message: "验证通过" }; const result = await dynamicForm.value.validate();
} else { if (result) {
return { valid: false, message: "验证失败" }; return { valid: true, message: "验证通过" };
} } else {
} catch { return { valid: false, message: "验证失败" };
return { valid: false, message: "验证失败" }; }
} } catch {
}; return { valid: false, message: "验证失败" };
}
onUnmounted(() => { };
emitter.off("changeNodeState");
emitter.off("contentChange"); onUnmounted(() => {
}); emitter.off("changeNodeState");
emitter.off("contentChange");
defineExpose({ });
validateForm,
setNodeProperties defineExpose({
}); validateForm,
</script> setNodeProperties
});
<style lang="scss" scoped> </script>
.node__container {
width: 100%; <style lang="scss" scoped>
height: auto; .node__container {
width: 100%;
.title__container { height: auto;
.title {
display: flex; .title__container {
align-items: center; .title {
display: flex;
img { align-items: center;
width: 24px;
height: 24px; img {
} width: 24px;
height: 24px;
.text { }
font-size: 16px;
font-weight: bold; .text {
margin-left: 12px; font-size: 16px;
} font-weight: bold;
} margin-left: 12px;
}
.subTitle { }
color: #737a87;
font-size: 12px; .subTitle {
margin: 8px 0; color: #737a87;
} font-size: 12px;
} margin: 8px 0;
}
.input__container { }
width: 100%;
background-color: #fafbfc; .input__container {
padding: 0 16px; width: 100%;
border-radius: 8px; background-color: #fafbfc;
box-sizing: border-box; padding: 0 16px;
border-radius: 8px;
.title { box-sizing: border-box;
height: 32px;
display: flex; .title {
align-items: center; height: 32px;
justify-content: space-between; display: flex;
align-items: center;
.left { justify-content: space-between;
display: flex;
align-items: center; .left {
display: flex;
.tag { align-items: center;
width: 3px;
height: 16px; .tag {
background: #1664ff; width: 3px;
border-radius: 0 4px 4px 0; height: 16px;
margin-right: 12px; background: #1664ff;
} border-radius: 0 4px 4px 0;
margin-right: 12px;
.text { }
font-size: 16px;
font-weight: 700; .text {
color: #0c0d0e; font-size: 16px;
} font-weight: 700;
} color: #0c0d0e;
}
.right { }
.addFormItem {
border: none; .right {
background: transparent; .addFormItem {
cursor: pointer; border: none;
} background: transparent;
} cursor: pointer;
} }
}
.form__container { }
margin: 12px 0;
.form__container {
.sub-properties { margin: 12px 0;
margin-left: 10px;
.zw { .sub-properties {
margin-left: 15px; margin-left: 10px;
&::before { .zw {
content: ""; margin-left: 15px;
position: absolute; &::before {
left: 0; content: "";
top: -4px; position: absolute;
width: 10px; left: 0;
border-left: 1px solid gray; top: -4px;
border-bottom: 1px solid gray; width: 10px;
border-bottom-left-radius: 4px; border-left: 1px solid gray;
background-color: transparent; border-bottom: 1px solid gray;
height: 24px; border-bottom-left-radius: 4px;
} background-color: transparent;
} height: 24px;
} }
}
.gSon-properties { }
margin-left: 10px;
.zw { .gSon-properties {
margin-left: 15px; margin-left: 10px;
&::before { .zw {
content: ""; margin-left: 15px;
position: absolute; &::before {
left: 0; content: "";
top: -4px; position: absolute;
width: 10px; left: 0;
border-left: 1px solid gray; top: -4px;
border-bottom: 1px solid gray; width: 10px;
border-bottom-left-radius: 4px; border-left: 1px solid gray;
background-color: transparent; border-bottom: 1px solid gray;
height: 24px; border-bottom-left-radius: 4px;
} background-color: transparent;
} height: 24px;
} }
}
.deleteBtn { }
margin-bottom: 22px;
cursor: pointer; .deleteBtn {
} margin-bottom: 22px;
cursor: pointer;
.addBtn { }
margin-bottom: 22px;
cursor: pointer; .addBtn {
} margin-bottom: 22px;
cursor: pointer;
:deep(.el-row) { }
align-items: end;
:deep(.el-row) {
.el-input { align-items: end;
--el-input-width: 120px;
} .el-input {
--el-input-width: 120px;
.el-select { }
--el-select-width: 120px;
} .el-select {
--el-select-width: 120px;
.el-cascader { }
--el-form-inline-content-width: 120px;
} .el-cascader {
} --el-form-inline-content-width: 120px;
} }
} }
} }
</style> }
}
<style lang="scss"> </style>
.popover__container {
min-width: 300px !important; <style lang="scss">
.popover__container {
.params__container { min-width: 300px !important;
margin-bottom: 12px;
.params__container {
.paramsTitle { margin-bottom: 12px;
color: #0c0d0e;
font-size: 14px; .paramsTitle {
font-weight: 500; color: #0c0d0e;
} font-size: 14px;
} font-weight: 500;
} }
</style> }
}
</style>

View File

@ -36,7 +36,7 @@ export default defineConfig(({mode, command}) => {
//赵 http://10.148.108.58:13080 //赵 http://10.148.108.58:13080
// dev http://10.148.20.34:13080 // dev http://10.148.20.34:13080
// target: command === 'build' ? VITE_API_URL : 'http://10.148.20.34:13080', // target: command === 'build' ? VITE_API_URL : 'http://10.148.20.34:13080',
target: command === 'build' ? VITE_API_URL : 'http://127.0.0.1:13080', target: command === 'build' ? VITE_API_URL : 'http://192.168.0.10:13080',
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '') rewrite: (p) => p.replace(/^\/dev-api/, '')
} }