2026-02-08 15:59:14 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="ks-model-builder-right">
|
|
|
|
|
<template v-if="currentElement">
|
|
|
|
|
|
|
|
|
|
<a-tabs v-model:activeKey="activeTopTabsKey" class="ks-model-builder-tabs settings-tab">
|
|
|
|
|
<template #leftExtra>
|
|
|
|
|
<span class="ks-model-builder-title-icon icon-input"></span>
|
|
|
|
|
</template>
|
|
|
|
|
<a-tab-pane key="1" tab="节点属性">
|
|
|
|
|
<a-form
|
|
|
|
|
autocomplete="off"
|
|
|
|
|
layout="vertical"
|
|
|
|
|
name="basic"
|
|
|
|
|
style="padding-bottom:15px;"
|
|
|
|
|
>
|
|
|
|
|
<a-form-item label="节点名称">
|
2026-02-08 16:01:21 +08:00
|
|
|
<a-input size="small" v-model:value="currentElement.name" :placeholder="currentElement.name" />
|
2026-02-08 15:59:14 +08:00
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item label="节点介绍">
|
2026-02-08 16:01:21 +08:00
|
|
|
<a-textarea size="small" v-model:value="currentElement.description" :placeholder="currentElement.description" />
|
2026-02-08 15:59:14 +08:00
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-divider />
|
|
|
|
|
|
|
|
|
|
<a-form-item label="输入">
|
2026-02-08 16:01:21 +08:00
|
|
|
<a-textarea size="small" v-model:value="currentElement.inputs" />
|
2026-02-08 15:59:14 +08:00
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item label="输出">
|
2026-02-08 16:01:21 +08:00
|
|
|
<a-textarea size="small" v-model:value="currentElement.outputs" />
|
2026-02-08 15:59:14 +08:00
|
|
|
</a-form-item>
|
|
|
|
|
|
2026-02-08 20:41:49 +08:00
|
|
|
<a-divider v-if="currentElement.settings && currentElement.parameters.length > 0"/>
|
2026-02-08 15:59:14 +08:00
|
|
|
|
2026-02-08 20:41:49 +08:00
|
|
|
<a-form-item :label="setting.description" v-for="setting in currentElement.parameters">
|
|
|
|
|
<a-input-number size="small" style="width:100%;" v-if="setting.dataType === 'double'" v-model:value="setting.defaultValue" :placeholder="setting.description" />
|
|
|
|
|
<a-input v-else size="small" v-model:value="setting.defaultValue" :placeholder="setting.description" />
|
2026-02-08 15:59:14 +08:00
|
|
|
</a-form-item>
|
|
|
|
|
</a-form>
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
|
|
|
|
|
</a-tabs>
|
|
|
|
|
|
|
|
|
|
<a-tabs v-model:activeKey="activeBottomTabsKey" class="ks-model-builder-tabs parameters-tabs">
|
|
|
|
|
<template #leftExtra>
|
|
|
|
|
<span class="ks-model-builder-title-icon icon-input"></span>
|
|
|
|
|
</template>
|
|
|
|
|
<a-tab-pane key="1" tab="节点变量">
|
|
|
|
|
<div class="w-full">
|
|
|
|
|
<a-space>
|
|
|
|
|
<a-button size="small" type="primary" @click="addVariable">添加</a-button>
|
|
|
|
|
</a-space>
|
|
|
|
|
<a-table
|
|
|
|
|
:columns="actionSpaceColumns"
|
|
|
|
|
:dataSource="currentElement.variables"
|
|
|
|
|
:pagination="false"
|
|
|
|
|
:scroll="{ x: 500 }"
|
|
|
|
|
class="mt-1"
|
|
|
|
|
row-key="key"
|
|
|
|
|
size="small"
|
|
|
|
|
style="overflow-y:auto;height:35vh;"
|
|
|
|
|
>
|
|
|
|
|
<template #bodyCell="{column, record, index}">
|
|
|
|
|
<template v-if="column.dataIndex === 'index'">
|
|
|
|
|
{{ index + 1 }}
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else-if="column.dataIndex === '_actions'">
|
|
|
|
|
<a-button
|
|
|
|
|
class="btn-link-delete"
|
|
|
|
|
danger
|
|
|
|
|
size="small"
|
|
|
|
|
type="text"
|
|
|
|
|
@click="()=> removeVariable(record)"
|
|
|
|
|
>
|
|
|
|
|
删除
|
|
|
|
|
</a-button>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
2026-02-08 16:01:21 +08:00
|
|
|
<a-input v-model:value="record[column.dataIndex]" size="small"/>
|
2026-02-08 15:59:14 +08:00
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
</a-table>
|
|
|
|
|
</div>
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
</a-tabs>
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<a-tabs v-else :activeKey="'0'" class="ks-model-builder-tabs parameters-tabs empty">
|
|
|
|
|
<template #leftExtra>
|
|
|
|
|
<span class="ks-model-builder-title-icon icon-input"></span>
|
|
|
|
|
</template>
|
|
|
|
|
<a-tab-pane :key="'0'" tab="请选择或者创建决策树">
|
|
|
|
|
<a-empty>
|
|
|
|
|
<template #description>
|
|
|
|
|
请选择或者创建决策树
|
|
|
|
|
</template>
|
|
|
|
|
</a-empty>
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
</a-tabs>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import { defineComponent, onMounted, type PropType, ref, watch } from 'vue';
|
|
|
|
|
import { CheckOutlined } from '@ant-design/icons-vue';
|
2026-02-08 20:27:40 +08:00
|
|
|
import type { ElementVariable, GraphTaskElement } from './builder/element';
|
2026-02-08 15:59:14 +08:00
|
|
|
import type { Graph, Node, NodeProperties } from '@antv/x6';
|
2026-02-08 20:27:40 +08:00
|
|
|
import { generateKey } from '@/utils/strings';
|
2026-02-08 15:59:14 +08:00
|
|
|
|
|
|
|
|
const actionSpaceColumns = [
|
|
|
|
|
{ title: '序号', dataIndex: 'index', key: 'index', width: 40 },
|
|
|
|
|
{ title: '变量名', dataIndex: 'name', key: 'name', width: 80 },
|
|
|
|
|
{ title: '参数值', dataIndex: 'value', key: 'value', width: 80 },
|
|
|
|
|
{ title: '单位', dataIndex: 'unit', key: 'unit', width: 80 },
|
|
|
|
|
{ title: '操作', dataIndex: '_actions', key: '_actions', width: 60 },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
|
components: { CheckOutlined },
|
|
|
|
|
props: {
|
|
|
|
|
node: { type: [Object, null] as PropType<Node<NodeProperties> | null | undefined>, required: false },
|
2026-02-08 16:01:21 +08:00
|
|
|
graph: { type: [Object, null] as PropType<Graph | null | undefined>, required: true }
|
2026-02-08 15:59:14 +08:00
|
|
|
},
|
|
|
|
|
emits: ['update-element'],
|
|
|
|
|
setup(props, { emit }) {
|
|
|
|
|
const activeTopTabsKey = ref<string>('1');
|
|
|
|
|
const activeBottomTabsKey = ref<string>('1');
|
|
|
|
|
const activeBottomTabs2Key = ref<string>('1');
|
|
|
|
|
|
|
|
|
|
const currentNode = ref<Node | null>(props.node ?? null);
|
2026-02-08 20:27:40 +08:00
|
|
|
const currentElement = ref<GraphTaskElement | null>(null);
|
2026-02-08 15:59:14 +08:00
|
|
|
|
|
|
|
|
const load = () => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const resolveNode = (n?: Node | null | undefined) => {
|
|
|
|
|
currentNode.value = n ?? null;
|
|
|
|
|
if (n) {
|
|
|
|
|
const data = n.getData();
|
2026-02-08 20:27:40 +08:00
|
|
|
currentElement.value = JSON.parse(JSON.stringify(data || {})) as GraphTaskElement;
|
2026-02-08 15:59:14 +08:00
|
|
|
} else {
|
|
|
|
|
currentElement.value = null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-08 16:01:21 +08:00
|
|
|
const addVariable = ()=> {
|
2026-02-08 15:59:14 +08:00
|
|
|
if (!currentElement.value) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!currentElement.value.variables) {
|
|
|
|
|
currentElement.value.variables = [];
|
|
|
|
|
}
|
|
|
|
|
currentElement.value?.variables.push({
|
|
|
|
|
key: generateKey('variable'),
|
|
|
|
|
name: null,
|
|
|
|
|
value: null,
|
|
|
|
|
defaults: null,
|
|
|
|
|
unit: null,
|
2026-02-08 16:01:21 +08:00
|
|
|
})
|
|
|
|
|
}
|
2026-02-08 15:59:14 +08:00
|
|
|
|
|
|
|
|
const removeVariable = (row: ElementVariable) => {
|
|
|
|
|
if (currentElement.value && currentElement.value.variables) {
|
|
|
|
|
const filteredVars = currentElement.value.variables.filter(v => v.key !== row.key);
|
|
|
|
|
currentElement.value.variables = [...filteredVars];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updateNode = () => {
|
|
|
|
|
if (currentNode.value && currentElement.value) {
|
|
|
|
|
// 深拷贝当前元素数据
|
2026-02-08 20:27:40 +08:00
|
|
|
const newElement = JSON.parse(JSON.stringify(currentElement.value)) as GraphTaskElement;
|
2026-02-08 15:59:14 +08:00
|
|
|
// 更新节点数据
|
|
|
|
|
currentNode.value.replaceData(newElement);
|
|
|
|
|
// 触发事件通知父组件
|
|
|
|
|
emit('update-element', newElement);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => props.node,
|
|
|
|
|
(n?: Node | null | undefined) => resolveNode(n),
|
|
|
|
|
{ deep: true, immediate: true },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
watch(() => currentElement.value, () => updateNode(), { deep: true });
|
|
|
|
|
|
|
|
|
|
onMounted(() => load());
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
actionSpaceColumns,
|
|
|
|
|
activeTopTabsKey,
|
|
|
|
|
activeBottomTabsKey,
|
|
|
|
|
activeBottomTabs2Key,
|
|
|
|
|
currentElement,
|
|
|
|
|
addVariable,
|
|
|
|
|
removeVariable,
|
|
|
|
|
// currentElementParameters,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
</script>
|