Initial commit

This commit is contained in:
libertyspy
2026-02-08 17:11:03 +08:00
parent a246c88341
commit 294e5d687e
5 changed files with 51 additions and 84 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 MiB

After

Width:  |  Height:  |  Size: 418 KiB

View File

@@ -8,7 +8,7 @@
*/
import { HttpRequestClient } from '@/utils/request';
import type { BehaviorTree, BehaviorTreeDetailsResponse, BehaviorTreePageResponse, NodeTemplatesResponse, TreeModelDetailsResponse, TreeModelGraph } from './types';
import type { BehaviorTree, BehaviorTreeDetailsResponse, BehaviorTreePageResponse, NodeTemplatesResponse } from './types';
import type { BasicResponse } from '@/types';
const req = HttpRequestClient.create<BasicResponse>({
@@ -23,17 +23,17 @@ export const findTreesByQuery = (query: Partial<BehaviorTree> = {}): Promise<Beh
return req.get<BehaviorTreePageResponse>('/system/behaviortree/list', query);
};
export const findOneTreeById = (id: number): Promise<BehaviorTreeDetailsResponse> => {
return req.get(`/system/behaviortree/${id}`);
};
export const updateTree = (rt: Partial<TreeModelGraph>): Promise<BasicResponse> => {
return req.postJson('/behavior-trees', rt);
export const updateTree = (rt: Partial<BehaviorTree>): Promise<BasicResponse> => {
return req.postJson('/system/behaviortree/${id}', rt);
};
export const createTree = (rt: Partial<TreeModelGraph>): Promise<BasicResponse> => {
return req.putJson('/behavior-trees', rt);
export const createTree = (rt: Partial<BehaviorTree>): Promise<BasicResponse> => {
return req.putJson('/system/behaviortree/${id}', rt);
};

View File

@@ -1,41 +0,0 @@
/*
* This file is part of the kernelstudio package.
*
* (c) 2014-2026 zlin <admin@kernelstudio.com>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/
import type { TreeModelsData, NodeTemplateQuery, NodeTemplateData } from './types';
import type { ApiPagination, ApiPaginationQuery } from '@/types';
export const defaultPagination = {
page: 1,
limit: 10,
total: 0,
total_pages: 0,
} as ApiPagination;
export const defaultTreeModelsData = {
trees: [],
pagination: { ...defaultPagination },
} as TreeModelsData;
export const defaultPaginationRequest = {
page: 1,
limit: 10,
keyword: null,
} as ApiPaginationQuery
export const defaultNodeTemplateQuery = {
page: 1,
limit: 1000,
keyword: null,
include_params: true,
} as NodeTemplateQuery
export const defaultNodeTemplateData = {
templates: [],
total: 0
} as NodeTemplateData

View File

@@ -17,7 +17,7 @@
<div class="ks-model-builder-content">
<div class="ks-model-builder-actions">
<a-space>
<a-tooltip v-if="graph && currentNodeGraph" placement="top">
<a-tooltip v-if="graph && currentBehaviorTree" placement="top">
<template #title>
保存
</template>
@@ -60,7 +60,7 @@
import { defineComponent, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import { message } from 'ant-design-vue';
import { getTeleport } from '@antv/x6-vue-shape';
import { Graph, Node,Edge, type NodeProperties } from '@antv/x6';
import { Graph, Node, type NodeProperties } from '@antv/x6';
import { CheckCircleOutlined, CheckOutlined, RollbackOutlined, SaveOutlined } from '@ant-design/icons-vue';
import { Wrapper } from '@/components/wrapper';
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
@@ -68,7 +68,7 @@ import Header from './header.vue';
import Properties from './properties.vue';
import { useGraphCanvas } from './builder/hooks';
import { registerNodeElement } from './builder/register';
import type { BehaviorTree, NodeGraph, NodeTemplate, SettingTaskNodeElement, TreeModel, TreeModelGraph } from './types';
import type { BehaviorTree, EdgeNodeElement, NodeGraph, NodeTemplate, SettingTaskNodeElement } from './types';
import { createTree, findOneTreeById, updateTree } from './api';
import { createTaskNodeElement, createTaskNodeElementFromTemplate, hasElements, hasRootElementNode, resolveNodeGraph } from './utils/node';
import TressCard from './trees-card.vue';
@@ -97,6 +97,7 @@ export default defineComponent({
const currentZoom = ref<number>(1);
const draggedNodeData = ref<NodeTemplate | null>(null);
const isDraggingOver = ref(false);
const currentBehaviorTree = ref<BehaviorTree | null>(null);
const currentNodeGraph = ref<NodeGraph | null>(null);
const selectedModelNode = ref<Node<NodeProperties> | null>(null);
const selectedNodeTaskElement = ref<SettingTaskNodeElement | null>(null);
@@ -151,7 +152,7 @@ export default defineComponent({
safeStopPropagation(e);
isDraggingOver.value = false;
if (!currentNodeGraph.value) {
if (!currentBehaviorTree.value) {
message.error('请先选择或者创建行为树.');
return;
}
@@ -200,26 +201,42 @@ export default defineComponent({
}
};
const handleSelectTree = (tree: BehaviorTree) => {
console.error('handleSelectTree', tree);
findOneTreeById(tree.id).then(r => {
if (r.data) {
currentBehaviorTree.value = r.data;
try {
currentBehaviorTree.value.graph = JSON.parse(r.data?.xmlContent as unknown as string) as unknown as NodeGraph;
} catch (e: any) {
console.error('parse error,cause:', e);
}
createElements();
} else {
message.error(r.msg ?? '行为树不存在.');
}
});
};
const createElements = () => {
if (!currentBehaviorTree.value?.graph) {
currentBehaviorTree.value?.graph = {
nodes: [],
edges: [],
};
}
if(graph.value && currentNodeGraph.value){
graph.value.clearCells();
setTimeout(()=> {
nextTick(()=> {
try{
if (currentNodeGraph.value && !currentNodeGraph.value?.graph){
currentNodeGraph.value.graph = {
nodes: [],
edges: [],
}
}
const nodes = currentNodeGraph.value?.graph?.nodes ?? [];
const edges = currentNodeGraph.value?.graph?.edges ?? [];
nodes.forEach(n=> {
const nodes: EdgeNodeElement[] = currentBehaviorTree.value?.graph?.nodes ?? [];
const edges: EdgeNodeElement[] = currentBehaviorTree.value?.graph?.edges ?? [];
nodes.forEach((n: any) => {
const node = createTaskNodeElement(n);
graph.value?.addNode(node as Node);
})
edges.forEach(g=> {
edges.forEach((g: any) => {
graph.value?.addEdge( g as any);
})
} catch (e){
@@ -293,40 +310,29 @@ export default defineComponent({
changed.value = true
};
const handleSelectTree = (treeModel: TreeModel) => {
console.error('handleSelectTree', treeModel);
findOneTreeById(treeModel.id).then(r => {
if (r.data) {
currentNodeGraph.value = r.data;
createElements();
} else {
message.error(r.message ?? '行为树不存在.');
}
});
};
const handleSave = () => {
const graphData: NodeGraph = resolveNodeGraph(graph.value as Graph);
console.info('handleSave', graphData);
if (!currentNodeGraph.value) {
if (!currentBehaviorTree.value) {
message.error('当前决策树不存在');
return;
}
const newModel: TreeModelGraph = {
...currentNodeGraph.value,
const newTree: BehaviorTree = {
...currentBehaviorTree.value,
graph: graphData,
xmlContent: JSON.stringify(graphData),
};
let res = null;
if (currentNodeGraph.value.id > 0) {
res = createTree(newModel);
if (currentBehaviorTree.value.id > 0) {
res = createTree(newTree);
} else {
res = updateTree(newModel);
res = updateTree(newTree);
}
res.then(r => {
if (r.code === 200) {
message.success(r.message ?? '操作成功.');
message.success(r.msg ?? '操作成功.');
} else {
message.error(r.message ?? '操作失败.');
message.error(r.msg ?? '操作失败.');
}
});
};
@@ -351,6 +357,7 @@ export default defineComponent({
});
return {
currentBehaviorTree,
currentNodeGraph,
selectedNodeTaskElement,
selectedModelNode,

View File

@@ -7,10 +7,10 @@
* that was distributed with this source code.
*/
import type { NullableString, PageableResponse, ApiDataResponse } from '@/types';
import type { ApiDataResponse, NullableString, PageableResponse } from '@/types';
import type { NodeGraph } from './node';
export interface BehaviorTree {
id: number,
name: NullableString,
description: NullableString,
@@ -18,6 +18,7 @@ export interface BehaviorTree {
updatedAt: NullableString,
englishName: NullableString,
xmlContent: NullableString,
graph: NodeGraph
}