UPDATE: VERSION-20260314
This commit is contained in:
@@ -1818,4 +1818,13 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background: #0d2d4e;
|
background: #0d2d4e;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ks-model-builder-body .ks-model-builder-left .ant-collapse {
|
||||||
|
&.platform-collapse{
|
||||||
|
.ant-collapse-content-box{
|
||||||
|
max-height: 45.5vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { HttpRequestClient } from '@/utils/request';
|
import { HttpRequestClient } from '@/utils/request';
|
||||||
import type { ScenarioPageableResponse, ScenarioRequest } from './types';
|
import type { PlatformWithComponentsResponse, ScenarioPageableResponse, ScenarioRequest } from './types';
|
||||||
import type { BasicResponse } from '@/types';
|
import type { BasicResponse } from '@/types';
|
||||||
|
|
||||||
const req = HttpRequestClient.create<BasicResponse>({
|
const req = HttpRequestClient.create<BasicResponse>({
|
||||||
@@ -34,4 +34,8 @@ export const findScenarioByQuery = (_query: Partial<ScenarioRequest> = {}): Prom
|
|||||||
|
|
||||||
export const deleteOneScenarioById = (id: number): Promise<BasicResponse> => {
|
export const deleteOneScenarioById = (id: number): Promise<BasicResponse> => {
|
||||||
return req.delete(`/system/behaviortree/${id}`);
|
return req.delete(`/system/behaviortree/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findPlatformWithComponents = (id: number): Promise<PlatformWithComponentsResponse> => {
|
||||||
|
return req.get(`system/firerule/platforms/${id}`);
|
||||||
};
|
};
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="ks-model-builder-content" style="width: calc(100% - 250px);">
|
<div class="ks-model-builder-content" style="width: calc(100% - 250px);">
|
||||||
<div class="ks-model-builder-actions">
|
<div class="ks-model-builder-actions">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button v-if="graph && currentBehaviorTree" class="ks-model-builder-save" size="small" @click="handleSave">
|
<a-button v-if="graph && currentScenario" class="ks-model-builder-save" size="small" @click="handleSave">
|
||||||
<CheckOutlined />
|
<CheckOutlined />
|
||||||
<span>保存</span>
|
<span>保存</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -51,7 +51,8 @@ import { CheckCircleOutlined, CheckOutlined, RollbackOutlined, SaveOutlined } fr
|
|||||||
import { Wrapper } from '@/components/wrapper';
|
import { Wrapper } from '@/components/wrapper';
|
||||||
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
||||||
import Header from '../header.vue';
|
import Header from '../header.vue';
|
||||||
import type { BehaviorTree, NodeDragTemplate, NodeTemplate } from '../types';
|
|
||||||
|
import type { currentScenario, NodeDragTemplate, NodeTemplate } from '../types';
|
||||||
import type { GraphTaskElement, NodeGraph } from '../builder/element';
|
import type { GraphTaskElement, NodeGraph } from '../builder/element';
|
||||||
import { useGraphCanvas } from '../builder/hooks';
|
import { useGraphCanvas } from '../builder/hooks';
|
||||||
import { registerNodeElement } from '../builder/register';
|
import { registerNodeElement } from '../builder/register';
|
||||||
@@ -59,6 +60,7 @@ import { createLineOptions } from '../builder/line';
|
|||||||
import { createTree, findOneTreeById, updateTree } from '../designer/api';
|
import { createTree, findOneTreeById, updateTree } from '../designer/api';
|
||||||
import { createGraphTaskElement, hasElements, hasRootElementNode, resolveNodeGraph } from '../builder/utils';
|
import { createGraphTaskElement, hasElements, hasRootElementNode, resolveNodeGraph } from '../builder/utils';
|
||||||
import { createGraphTaskElementFromTemplate } from '../utils/node';
|
import { createGraphTaskElementFromTemplate } from '../utils/node';
|
||||||
|
|
||||||
import PlatformCard from './platform-card.vue';
|
import PlatformCard from './platform-card.vue';
|
||||||
import NodesCard from './nodes-card.vue';
|
import NodesCard from './nodes-card.vue';
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ export default defineComponent({
|
|||||||
const draggedNodeData = ref<NodeDragTemplate | null>(null);
|
const draggedNodeData = ref<NodeDragTemplate | null>(null);
|
||||||
const isDraggingOver = ref(false);
|
const isDraggingOver = ref(false);
|
||||||
const currentTreeEditing = ref<boolean>(false);
|
const currentTreeEditing = ref<boolean>(false);
|
||||||
const currentBehaviorTree = ref<BehaviorTree | null>(null);
|
const currentScenario = ref<currentScenario | null>(null);
|
||||||
const currentNodeGraph = ref<NodeGraph | null>(null);
|
const currentNodeGraph = ref<NodeGraph | null>(null);
|
||||||
const selectedModelNode = ref<Node<NodeProperties> | null>(null);
|
const selectedModelNode = ref<Node<NodeProperties> | null>(null);
|
||||||
const selectedNodeTaskElement = ref<GraphTaskElement | null>(null);
|
const selectedNodeTaskElement = ref<GraphTaskElement | null>(null);
|
||||||
@@ -142,7 +144,7 @@ export default defineComponent({
|
|||||||
isDraggingOver.value = false;
|
isDraggingOver.value = false;
|
||||||
currentTreeEditing.value = false;
|
currentTreeEditing.value = false;
|
||||||
|
|
||||||
if (!currentBehaviorTree.value) {
|
if (!currentScenario.value) {
|
||||||
message.error('请先选择或者创建行为树.');
|
message.error('请先选择或者创建行为树.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -191,7 +193,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectTree = (tree: BehaviorTree) => {
|
const handleSelectTree = (tree: currentScenario) => {
|
||||||
console.info('handleSelectTree', tree);
|
console.info('handleSelectTree', tree);
|
||||||
findOneTreeById(tree.id).then(r => {
|
findOneTreeById(tree.id).then(r => {
|
||||||
if (r.data) {
|
if (r.data) {
|
||||||
@@ -207,7 +209,7 @@ export default defineComponent({
|
|||||||
edges: [],
|
edges: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
currentBehaviorTree.value = {
|
currentScenario.value = {
|
||||||
...r.data,
|
...r.data,
|
||||||
graph: nodeGraph,
|
graph: nodeGraph,
|
||||||
};
|
};
|
||||||
@@ -227,19 +229,19 @@ export default defineComponent({
|
|||||||
console.error('clear cells error, cause:', e);
|
console.error('clear cells error, cause:', e);
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (currentBehaviorTree.value?.graph && graph.value) {
|
if (currentScenario.value?.graph && graph.value) {
|
||||||
if (currentBehaviorTree.value?.graph.nodes) {
|
if (currentScenario.value?.graph.nodes) {
|
||||||
currentBehaviorTree.value?.graph.nodes.forEach(ele => {
|
currentScenario.value?.graph.nodes.forEach(ele => {
|
||||||
const node = createGraphTaskElement(ele as GraphTaskElement);
|
const node = createGraphTaskElement(ele as GraphTaskElement);
|
||||||
console.info('create node: ', ele);
|
console.info('create node: ', ele);
|
||||||
// 将节点添加到画布
|
// 将节点添加到画布
|
||||||
graph.value?.addNode(node as Node);
|
graph.value?.addNode(node as Node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (currentBehaviorTree.value?.graph.edges) {
|
if (currentScenario.value?.graph.edges) {
|
||||||
// 然后添加所有边,确保包含桩点信息
|
// 然后添加所有边,确保包含桩点信息
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
currentBehaviorTree.value?.graph.edges.forEach(edgeData => {
|
currentScenario.value?.graph.edges.forEach(edgeData => {
|
||||||
graph.value?.addEdge({
|
graph.value?.addEdge({
|
||||||
...edgeData,
|
...edgeData,
|
||||||
...createLineOptions(),
|
...createLineOptions(),
|
||||||
@@ -253,7 +255,7 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateTree = () => {
|
const handleCreateTree = () => {
|
||||||
currentBehaviorTree.value = {
|
currentScenario.value = {
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '行为树',
|
name: '行为树',
|
||||||
description: null,
|
description: null,
|
||||||
@@ -296,7 +298,7 @@ export default defineComponent({
|
|||||||
handleGraphEvent('blank:click', () => {
|
handleGraphEvent('blank:click', () => {
|
||||||
selectedModelNode.value = null;
|
selectedModelNode.value = null;
|
||||||
selectedNodeTaskElement.value = null;
|
selectedNodeTaskElement.value = null;
|
||||||
currentTreeEditing.value = null !== currentBehaviorTree.value;
|
currentTreeEditing.value = null !== currentScenario.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
handleGraphEvent('node:click', (args: any) => {
|
handleGraphEvent('node:click', (args: any) => {
|
||||||
@@ -348,12 +350,12 @@ export default defineComponent({
|
|||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const graphData: NodeGraph = resolveNodeGraph(graph.value as Graph);
|
const graphData: NodeGraph = resolveNodeGraph(graph.value as Graph);
|
||||||
console.info('handleSave', graphData);
|
console.info('handleSave', graphData);
|
||||||
if (!currentBehaviorTree.value) {
|
if (!currentScenario.value) {
|
||||||
message.error('当前决策树不存在');
|
message.error('当前决策树不存在');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newTree: BehaviorTree = {
|
const newTree: currentScenario = {
|
||||||
...currentBehaviorTree.value,
|
...currentScenario.value,
|
||||||
graph: graphData,
|
graph: graphData,
|
||||||
xmlContent: JSON.stringify(graphData),
|
xmlContent: JSON.stringify(graphData),
|
||||||
};
|
};
|
||||||
@@ -366,7 +368,7 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let res = null;
|
let res = null;
|
||||||
if (currentBehaviorTree.value.id > 0) {
|
if (currentScenario.value.id > 0) {
|
||||||
res = createTree(newTree);
|
res = createTree(newTree);
|
||||||
} else {
|
} else {
|
||||||
res = updateTree(newTree);
|
res = updateTree(newTree);
|
||||||
@@ -404,7 +406,7 @@ export default defineComponent({
|
|||||||
treesCardRef,
|
treesCardRef,
|
||||||
handleCreateTree,
|
handleCreateTree,
|
||||||
currentTreeEditing,
|
currentTreeEditing,
|
||||||
currentBehaviorTree,
|
currentScenario,
|
||||||
currentNodeGraph,
|
currentNodeGraph,
|
||||||
selectedNodeTaskElement,
|
selectedNodeTaskElement,
|
||||||
selectedModelNode,
|
selectedModelNode,
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<a-collapse v-model:activeKey="activeKey" :accordion="true">
|
<a-collapse v-model:activeKey="activeKey" :accordion="true" class="platform-collapse">
|
||||||
<a-collapse-panel key="1">
|
<a-collapse-panel key="1">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span class="ks-model-builder-title-icon icon-model"></span>控制节点
|
<span class="ks-model-builder-title-icon icon-model"></span>平台名称
|
||||||
</template>
|
</template>
|
||||||
<div class="w-full h-full">
|
<div class="w-full h-full">
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col v-for="nm in controlTemplates" :span="12">
|
<a-col v-for="nm in templateData" :span="12">
|
||||||
<div
|
<div
|
||||||
:key="nm.id"
|
:key="nm.id"
|
||||||
:data-type="nm.type"
|
|
||||||
class="ks-model-drag-item"
|
class="ks-model-drag-item"
|
||||||
@dragend="handleDragEnd"
|
@dragend="handleDragEnd"
|
||||||
@dragstart="handleDragStart($event, nm, 'control')"
|
@dragstart="handleDragStart($event, nm)"
|
||||||
>
|
>
|
||||||
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
<img :alt="nm.description ?? nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
||||||
<span class="desc">{{ nm.name }}</span>
|
<span class="desc">{{ nm.description ?? nm.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
@@ -29,49 +28,29 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, onMounted, ref } from 'vue';
|
import { defineComponent, onMounted, ref } from 'vue';
|
||||||
import type { NodeDragTemplate, NodeTemplate } from '../types';
|
|
||||||
import { findNodeTemplates } from '../designer/api';
|
|
||||||
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
||||||
|
import {findPlatformWithComponents} from './api'
|
||||||
|
import {type PlatformWithComponents} from './types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
emits: ['drag-item-start', 'drag-item-end'],
|
emits: ['drag-item-start', 'drag-item-end'],
|
||||||
setup(_props, { emit }) {
|
setup(_props, { emit }) {
|
||||||
|
|
||||||
const activeKey = ref<number>(1);
|
const activeKey = ref<number>(1);
|
||||||
const templateData = ref<NodeTemplate[]>([]);
|
const templateData = ref<PlatformWithComponents[]>([]);
|
||||||
const isDraggingOver = ref<boolean>(false);
|
const isDraggingOver = ref<boolean>(false);
|
||||||
const draggedNodeData = ref<NodeDragTemplate | null>(null);
|
const draggedNodeData = ref<PlatformWithComponents | null>(null);
|
||||||
// 控制节点
|
|
||||||
const controlTemplates = ref<NodeTemplate[]>([]);
|
|
||||||
// 条件节点
|
|
||||||
const conditionTemplates = ref<NodeTemplate[]>([]);
|
|
||||||
// 行为节点
|
|
||||||
const actionsTemplates = ref<NodeTemplate[]>([]);
|
|
||||||
|
|
||||||
const loadTress = () => {
|
const loadTress = () => {
|
||||||
controlTemplates.value = [];
|
templateData.value = []
|
||||||
conditionTemplates.value = [];
|
findPlatformWithComponents(1).then(r => {
|
||||||
actionsTemplates.value = [];
|
templateData.value = r.data ?? []
|
||||||
|
|
||||||
findNodeTemplates().then(r => {
|
|
||||||
templateData.value = r.data;
|
|
||||||
if (r.data) {
|
|
||||||
r.data.forEach(tpl => {
|
|
||||||
if (tpl.type === 'action') {
|
|
||||||
actionsTemplates.value.push(tpl);
|
|
||||||
} else if (tpl.type === 'parallel' || tpl.type === 'sequence' || tpl.type === 'select'|| tpl.type === 'root') {
|
|
||||||
controlTemplates.value.push(tpl);
|
|
||||||
} else {
|
|
||||||
conditionTemplates.value.push(tpl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDragStart = (e: DragEvent, nm: NodeTemplate, group: String) => {
|
const handleDragStart = (e: DragEvent, nm: PlatformWithComponents) => {
|
||||||
let dragNode: NodeDragTemplate = { ...nm, group: group };
|
let dragNode: PlatformWithComponents = { ...nm };
|
||||||
draggedNodeData.value = dragNode as NodeDragTemplate;
|
draggedNodeData.value = dragNode as PlatformWithComponents;
|
||||||
|
|
||||||
if (e.dataTransfer) {
|
if (e.dataTransfer) {
|
||||||
e.dataTransfer.setData('text/plain', JSON.stringify(draggedNodeData.value));
|
e.dataTransfer.setData('text/plain', JSON.stringify(draggedNodeData.value));
|
||||||
@@ -105,17 +84,21 @@ export default defineComponent({
|
|||||||
emit('drag-item-end', isDraggingOver.value, e);
|
emit('drag-item-end', isDraggingOver.value, e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const load = ()=> {
|
||||||
|
findPlatformWithComponents(1).then(re=> {
|
||||||
|
console.error(re);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadTress();
|
loadTress();
|
||||||
|
load();
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activeKey,
|
activeKey,
|
||||||
|
templateData,
|
||||||
controlTemplates,
|
|
||||||
conditionTemplates,
|
|
||||||
actionsTemplates,
|
|
||||||
|
|
||||||
handleDragStart,
|
handleDragStart,
|
||||||
handleDragEnd,
|
handleDragEnd,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import type { NullableString, PageableResponse } from '@/types';
|
import type { ApiDataResponse, NullableString, PageableResponse } from '@/types';
|
||||||
import type { FireRule } from '@/views/decision/rule/types.ts';
|
|
||||||
|
|
||||||
export interface Scenario {
|
export interface Scenario {
|
||||||
id: number,
|
id: number,
|
||||||
@@ -17,11 +16,34 @@ export interface Scenario {
|
|||||||
description: NullableString,
|
description: NullableString,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScenarioRequest extends FireRule {
|
export interface ScenarioRequest extends Scenario {
|
||||||
pageNum: number,
|
pageNum: number,
|
||||||
pageSize: number,
|
pageSize: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScenarioPageableResponse extends PageableResponse<Scenario> {
|
export interface ScenarioPageableResponse extends PageableResponse<Scenario> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Platform {
|
||||||
|
id: number,
|
||||||
|
name: NullableString,
|
||||||
|
description: NullableString,
|
||||||
|
scenarioId: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlatformComponent {
|
||||||
|
id: number,
|
||||||
|
name: NullableString,
|
||||||
|
type: NullableString,
|
||||||
|
description: NullableString,
|
||||||
|
platformId: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlatformWithComponents extends Platform {
|
||||||
|
components: PlatformComponent[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlatformWithComponentsResponse extends ApiDataResponse<PlatformWithComponents[]> {
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user