UPDATE: VERSION-20260314

This commit is contained in:
libertyspy
2026-03-14 22:35:21 +08:00
parent 1504c3fc1b
commit 2e55254412
5 changed files with 84 additions and 64 deletions

View File

@@ -1819,3 +1819,12 @@
background: #0d2d4e; background: #0d2d4e;
} }
} }
.ks-model-builder-body .ks-model-builder-left .ant-collapse {
&.platform-collapse{
.ant-collapse-content-box{
max-height: 45.5vh;
}
}
}

View File

@@ -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>({
@@ -35,3 +35,7 @@ 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}`);
};

View File

@@ -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,

View File

@@ -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,
}; };

View File

@@ -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,7 +16,7 @@ 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,
} }
@@ -25,3 +24,26 @@ export interface ScenarioRequest extends FireRule {
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[]> {
}