Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,94 +1,96 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-dropdown
|
<div>
|
||||||
:trigger="['contextmenu']"
|
<a-dropdown
|
||||||
:getPopupContainer="getPopupContainer"
|
:trigger="['contextmenu']"
|
||||||
@openChange="handleVisibleChange"
|
:getPopupContainer="getPopupContainer"
|
||||||
>
|
@openChange="handleVisibleChange"
|
||||||
<a-card
|
|
||||||
:class="[
|
|
||||||
'ks-scenario-node',
|
|
||||||
`ks-scenario-${element?.category ?? 'model'}-node`
|
|
||||||
]"
|
|
||||||
hoverable
|
|
||||||
>
|
>
|
||||||
<template #title>
|
<a-card
|
||||||
<a-space>
|
:class="[
|
||||||
<span class="ks-scenario-node-title">{{ element?.description ?? element?.name ?? '-' }}</span>
|
'ks-scenario-node',
|
||||||
</a-space>
|
`ks-scenario-${element?.category ?? 'model'}-node`
|
||||||
</template>
|
]"
|
||||||
|
hoverable
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<a-space>
|
||||||
|
<span class="ks-scenario-node-title">{{ element?.description ?? element?.name ?? '-' }}</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 节点内容区域 -->
|
<!-- 节点内容区域 -->
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="ks-scenario-node-content">
|
<div class="ks-scenario-node-content">
|
||||||
<div
|
|
||||||
v-for="(item, index) in element?.components || []"
|
|
||||||
:key="item.id || index"
|
|
||||||
class="ks-scenario-node-row"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
:data-port="`in-${item.id || index}`"
|
v-for="(item, index) in element?.components || []"
|
||||||
:port="`in-${item.id || index}`"
|
:key="item.id || index"
|
||||||
:title="`入桩: ${item.name}`"
|
class="ks-scenario-node-row"
|
||||||
class="port port-in"
|
|
||||||
magnet="passive"
|
|
||||||
:data-item="JSON.stringify(item)"
|
|
||||||
>
|
>
|
||||||
<div class="triangle-left"></div>
|
<div
|
||||||
</div>
|
:data-port="`in-${item.id || index}`"
|
||||||
|
:port="`in-${item.id || index}`"
|
||||||
|
:title="`入桩: ${item.name}`"
|
||||||
|
class="port port-in"
|
||||||
|
magnet="passive"
|
||||||
|
:data-item="JSON.stringify(item)"
|
||||||
|
>
|
||||||
|
<div class="triangle-left"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- child名称 -->
|
<!-- child名称 -->
|
||||||
<div class="ks-scenario-node-name">
|
<div class="ks-scenario-node-name">
|
||||||
{{ substring(item.description ?? item.name, 20) }}
|
{{ substring(item.description ?? item.name, 20) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右侧出桩:只能作为连线源 -->
|
<!-- 右侧出桩:只能作为连线源 -->
|
||||||
<div
|
<div
|
||||||
:data-port="`out-${item.id || index}`"
|
:data-port="`out-${item.id || index}`"
|
||||||
:port="`out-${item.id || index}`"
|
:port="`out-${item.id || index}`"
|
||||||
:title="`出桩: ${item.name}`"
|
:title="`出桩: ${item.name}`"
|
||||||
class="port port-out"
|
class="port port-out"
|
||||||
magnet="active"
|
magnet="active"
|
||||||
:data-item="JSON.stringify(item)"
|
:data-item="JSON.stringify(item)"
|
||||||
>
|
>
|
||||||
<div class="triangle-right" ></div>
|
<div class="triangle-right" ></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a-card>
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-menu @click="handleMenuClick">
|
<a-menu @click="handleMenuClick">
|
||||||
<a-sub-menu key="mount">
|
<a-sub-menu key="mount">
|
||||||
<template #icon>
|
|
||||||
<LinkOutlined />
|
|
||||||
</template>
|
|
||||||
<template #title>挂载</template>
|
|
||||||
<a-menu-item
|
|
||||||
v-for="tree in availableTrees"
|
|
||||||
:key="`tree-${tree.id}`"
|
|
||||||
:disabled="isTreeMounted(tree.id)"
|
|
||||||
@click="() => handleMountTree(tree)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CheckOutlined v-if="isTreeMounted(tree.id)" />
|
<LinkOutlined />
|
||||||
</template>
|
</template>
|
||||||
{{ tree.name }}
|
<template #title>挂载</template>
|
||||||
|
<a-menu-item
|
||||||
|
v-for="tree in availableTrees"
|
||||||
|
:key="`tree-${tree.id}`"
|
||||||
|
:disabled="isTreeMounted(tree.id)"
|
||||||
|
@click="() => handleMountTree(tree)"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<CheckOutlined v-if="isTreeMounted(tree.id)" />
|
||||||
|
</template>
|
||||||
|
{{ tree.name }}
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item v-if="availableTrees.length === 0" disabled>
|
||||||
|
暂无可用行为树
|
||||||
|
</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
<a-menu-divider />
|
||||||
|
<a-menu-item key="delete">
|
||||||
|
<template #icon>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</template>
|
||||||
|
删除
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item v-if="availableTrees.length === 0" disabled>
|
</a-menu>
|
||||||
暂无可用行为树
|
</template>
|
||||||
</a-menu-item>
|
</a-dropdown>
|
||||||
</a-sub-menu>
|
</div>
|
||||||
<a-menu-divider />
|
|
||||||
<a-menu-item key="delete">
|
|
||||||
<template #icon>
|
|
||||||
<DeleteOutlined />
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -99,7 +101,7 @@ import { DeleteOutlined, LinkOutlined, CheckOutlined, SettingOutlined } from '@a
|
|||||||
import type { Graph } from '@antv/x6';
|
import type { Graph } from '@antv/x6';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { substring } from '@/utils/strings';
|
import { substring } from '@/utils/strings';
|
||||||
import { getAllBehaviorTreesBySceneId, updateBehaviorTree } from './api';
|
import { updateBehaviorTree } from './api';
|
||||||
import type { BehaviorTree } from '../designer/tree';
|
import type { BehaviorTree } from '../designer/tree';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|||||||
@@ -1,49 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-dropdown :trigger="['contextmenu']" @openChange="handleVisibleChange">
|
<div>
|
||||||
<a-card
|
<a-dropdown :trigger="['contextmenu']" @openChange="handleVisibleChange">
|
||||||
:class="[
|
|
||||||
'ks-designer-node',
|
|
||||||
`ks-designer-${element?.category ?? 'model'}-node`,
|
<a-card
|
||||||
`ks-designer-group-${element?.group ?? 'general'}`
|
:class="[
|
||||||
]"
|
'ks-designer-node',
|
||||||
hoverable
|
`ks-designer-${element?.category ?? 'model'}-node`,
|
||||||
>
|
`ks-designer-group-${element?.group ?? 'general'}`
|
||||||
<template #title>
|
]"
|
||||||
<a-space>
|
hoverable
|
||||||
<!-- <span class="ks-designer-node-icon"></span>-->
|
>
|
||||||
<span class="ks-designer-node-title">{{ element?.name ?? '-' }}</span>
|
<template #title>
|
||||||
</a-space>
|
<a-space>
|
||||||
|
<!-- <span class="ks-designer-node-icon"></span>-->
|
||||||
|
<span class="ks-designer-node-title">{{ element?.name ?? '-' }}</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="port port-in" data-port="in-0" magnet="passive">
|
||||||
|
<div class="triangle-left"></div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full ks-designer-node-text">
|
||||||
|
<a-tooltip >
|
||||||
|
<template #title>
|
||||||
|
{{ element?.description ?? element?.name }}
|
||||||
|
</template>
|
||||||
|
<p class="ks-designer-node-label">
|
||||||
|
{{ substring(element?.name ?? (element?.name ?? '-'), 40) }}
|
||||||
|
</p>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="port port-out" data-port="out-0" magnet="active">
|
||||||
|
<div class="triangle-right" ></div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<template #overlay>
|
||||||
|
<a-menu @click="handleMenuClick">
|
||||||
|
<a-menu-item key="delete">
|
||||||
|
<template #icon>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</template>
|
||||||
|
删除
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
</template>
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
<div class="port port-in" data-port="in-0" magnet="passive">
|
</div>
|
||||||
<div class="triangle-left"></div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full ks-designer-node-text">
|
|
||||||
<a-tooltip >
|
|
||||||
<template #title>
|
|
||||||
{{ element?.description ?? element?.name }}
|
|
||||||
</template>
|
|
||||||
<p class="ks-designer-node-label">
|
|
||||||
{{ substring(element?.name ?? (element?.name ?? '-'), 40) }}
|
|
||||||
</p>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="port port-out" data-port="out-0" magnet="active">
|
|
||||||
<div class="triangle-right" ></div>
|
|
||||||
</div>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<template #overlay>
|
|
||||||
<a-menu @click="handleMenuClick">
|
|
||||||
<a-menu-item key="delete">
|
|
||||||
<template #icon>
|
|
||||||
<DeleteOutlined />
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|||||||
@@ -154,23 +154,6 @@
|
|||||||
<a-input v-else v-model:value="setting.defaultValue" :placeholder="setting.description" size="small" />
|
<a-input v-else v-model:value="setting.defaultValue" :placeholder="setting.description" size="small" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
<template>
|
|
||||||
<a-form-item v-for="setting in currentElement.parameters" :label="setting.description">
|
|
||||||
<a-input-number v-if="setting.dataType === 'double'" v-model:value="setting.defaultValue"
|
|
||||||
:placeholder="setting.description" size="small" style="width:100%;" />
|
|
||||||
<a-select :placeholder="`请选择${setting.description}`"
|
|
||||||
allow-clear
|
|
||||||
v-else-if="setting.paramKey === 'platforms'" v-model:value="setting.defaultValue">
|
|
||||||
<a-select-option v-for="pl in getAvailablePlatforms()" :value="pl.name">{{ pl.description }}</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select :placeholder="`请选择${setting.description}`"
|
|
||||||
allow-clear
|
|
||||||
v-else-if="setting.paramKey === 'command'" v-model:value="setting.defaultValue">
|
|
||||||
<a-select-option v-for="pl in nodeCommands" :value="pl.command">{{pl.chineseName}}</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-input v-else v-model:value="setting.defaultValue" :placeholder="setting.description" size="small" />
|
|
||||||
</a-form-item>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</a-form>
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<a-list :data-source="scenarios || []" size="small" style="min-height: 25vh">
|
<a-list :data-source="scenarios || []" size="small" style="min-height: 25vh">
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item @click="()=> handleSelect(item)">
|
<a-list-item :class="{ 'ks-item-selected': selectedId === item.id }" @click="()=> handleSelect(item)">
|
||||||
<a-flex>
|
<a-flex>
|
||||||
<a-tooltip placement="bottom">
|
<a-tooltip placement="bottom">
|
||||||
<template #title>
|
<template #title>
|
||||||
@@ -23,20 +23,6 @@
|
|||||||
</template>
|
</template>
|
||||||
<span>{{ substring(item.name, 15) }}</span>
|
<span>{{ substring(item.name, 15) }}</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-flex class="ks-tree-actions">
|
|
||||||
<a-popconfirm
|
|
||||||
title="确定复制?"
|
|
||||||
@confirm="()=> handleCopy(item)"
|
|
||||||
>
|
|
||||||
<span class="ks-tree-action ks-tree-action-copy" @click.stop style="margin-right: 10px"><CopyOutlined /></span>
|
|
||||||
</a-popconfirm>
|
|
||||||
<a-popconfirm
|
|
||||||
title="确定删除?"
|
|
||||||
@confirm="()=> handleDelete(item)"
|
|
||||||
>
|
|
||||||
<span class="ks-tree-action ks-tree-action-delete" @click.stop><DeleteOutlined /></span>
|
|
||||||
</a-popconfirm>
|
|
||||||
</a-flex>
|
|
||||||
</a-flex>
|
</a-flex>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</template>
|
</template>
|
||||||
@@ -74,6 +60,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
const activeKey = ref<number>(0);
|
const activeKey = ref<number>(0);
|
||||||
const totalScenarios = ref<number>(0);
|
const totalScenarios = ref<number>(0);
|
||||||
|
const selectedId = ref<number | null>(null);
|
||||||
|
|
||||||
const loadScenarios = (cb?: () => void) => {
|
const loadScenarios = (cb?: () => void) => {
|
||||||
findScenarioByQuery(scenarioQuery.value).then(r => {
|
findScenarioByQuery(scenarioQuery.value).then(r => {
|
||||||
@@ -89,19 +76,8 @@ export default defineComponent({
|
|||||||
loadScenarios();
|
loadScenarios();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (item: Scenario) => {
|
|
||||||
// TODO: 实现删除场景的API调用
|
|
||||||
console.log('删除场景:', item);
|
|
||||||
loadScenarios();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCopy = (item: Scenario) => {
|
|
||||||
// TODO: 实现复制场景的API调用
|
|
||||||
console.log('复制场景:', item);
|
|
||||||
loadScenarios();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelect = (record: Scenario) => {
|
const handleSelect = (record: Scenario) => {
|
||||||
|
selectedId.value = record.id;
|
||||||
emit('select-scenario', record);
|
emit('select-scenario', record);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,6 +86,7 @@ export default defineComponent({
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadScenarios(() => {
|
loadScenarios(() => {
|
||||||
if(scenarios.value.length > 0){
|
if(scenarios.value.length > 0){
|
||||||
|
selectedId.value = scenarios.value[0]!.id;
|
||||||
emit('select-scenario', scenarios.value[0]);
|
emit('select-scenario', scenarios.value[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -120,42 +97,18 @@ export default defineComponent({
|
|||||||
totalScenarios,
|
totalScenarios,
|
||||||
substring,
|
substring,
|
||||||
activeKey,
|
activeKey,
|
||||||
|
selectedId,
|
||||||
scenarios,
|
scenarios,
|
||||||
scenarioQuery,
|
scenarioQuery,
|
||||||
loadScenarios,
|
loadScenarios,
|
||||||
handleSelect,
|
handleSelect,
|
||||||
handleChange,
|
handleChange,
|
||||||
handleDelete,
|
|
||||||
handleCopy,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.ks-tree-actions {
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ks-tree-action {
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 2px 5px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ks-tree-action:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ks-tree-action-copy {
|
|
||||||
color: #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ks-tree-action-delete {
|
|
||||||
color: #ff4d4f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.a-list-item {
|
.a-list-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
@@ -166,14 +119,16 @@ export default defineComponent({
|
|||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.a-list-item:hover .ks-tree-actions {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-scenario::before {
|
.icon-scenario::before {
|
||||||
content: '\e6b8';
|
content: '\e6b8';
|
||||||
font-family: 'iconfont';
|
font-family: 'iconfont';
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
color: #82c4e9;
|
color: #82c4e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.ant-list-item.ks-item-selected) {
|
||||||
|
background-color: rgba(130, 196, 233, 0.15);
|
||||||
|
border-left: 3px solid #82c4e9;
|
||||||
|
padding-left: 9px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export interface BehaviorTree {
|
|||||||
xmlContent: NullableString,
|
xmlContent: NullableString,
|
||||||
graph: GraphContainer
|
graph: GraphContainer
|
||||||
platformId: null | number
|
platformId: null | number
|
||||||
|
scenarioId?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BehaviorTreeRequest extends BehaviorTree {
|
export interface BehaviorTreeRequest extends BehaviorTree {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<a-list :data-source="behaviorTrees || []" size="small" style="min-height: 25vh">
|
<a-list :data-source="behaviorTrees || []" size="small" style="min-height: 25vh">
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item @click="()=> handleSelect(item)">
|
<a-list-item :class="{ 'ks-item-selected': selectedId === item.id }" @click="()=> handleSelect(item)">
|
||||||
<a-flex>
|
<a-flex>
|
||||||
<a-tooltip placement="bottom">
|
<a-tooltip placement="bottom">
|
||||||
<template #title>
|
<template #title>
|
||||||
@@ -86,10 +86,12 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
const activeKey = ref<number>(1);
|
const activeKey = ref<number>(1);
|
||||||
const totalTress = ref<number>(0);
|
const totalTress = ref<number>(0);
|
||||||
|
const selectedId = ref<number | null>(null);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => _props.scenarioId,
|
() => _props.scenarioId,
|
||||||
() => {
|
() => {
|
||||||
|
selectedId.value = null;
|
||||||
if (!_props.scenarioId) {
|
if (!_props.scenarioId) {
|
||||||
behaviorTrees.value = [];
|
behaviorTrees.value = [];
|
||||||
totalTress.value = 0;
|
totalTress.value = 0;
|
||||||
@@ -139,6 +141,7 @@ export default defineComponent({
|
|||||||
];
|
];
|
||||||
|
|
||||||
const handleSelect = (record: BehaviorTree) => {
|
const handleSelect = (record: BehaviorTree) => {
|
||||||
|
selectedId.value = record.id;
|
||||||
emit('select-tree', record);
|
emit('select-tree', record);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,6 +160,7 @@ export default defineComponent({
|
|||||||
totalTress,
|
totalTress,
|
||||||
substring,
|
substring,
|
||||||
activeKey,
|
activeKey,
|
||||||
|
selectedId,
|
||||||
behaviorTrees,
|
behaviorTrees,
|
||||||
behaviorTreeQuery,
|
behaviorTreeQuery,
|
||||||
loadTress,
|
loadTress,
|
||||||
@@ -172,3 +176,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.ant-list-item.ks-item-selected) {
|
||||||
|
background-color: rgba(130, 196, 233, 0.15);
|
||||||
|
border-left: 3px solid #82c4e9;
|
||||||
|
padding-left: 9px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user