UPDATE: VERSION-20260313
This commit is contained in:
@@ -79,7 +79,7 @@ export const createGraphConnectingAttributes = (): Partial<Connecting> => {
|
|||||||
const targetData = targetCell.getData() as ModelElement;
|
const targetData = targetCell.getData() as ModelElement;
|
||||||
|
|
||||||
// 根节点不能作为子节点
|
// 根节点不能作为子节点
|
||||||
if (targetData.type === 'startEvent') {
|
if (targetData.category === 'root') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,19 @@
|
|||||||
<a-card
|
<a-card
|
||||||
:class="[
|
:class="[
|
||||||
'ks-designer-node',
|
'ks-designer-node',
|
||||||
`ks-designer-${element?.category ?? 'model'}-node`
|
`ks-designer-${element?.category ?? 'model'}-node`,
|
||||||
|
`ks-designer-group-${element?.group ?? 'general'}`
|
||||||
]"
|
]"
|
||||||
hoverable
|
hoverable
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<span class="ks-designer-node-icon"></span>
|
<!-- <span class="ks-designer-node-icon"></span>-->
|
||||||
<span class="ks-designer-node-title">{{ element?.name ?? '-' }}</span>
|
<span class="ks-designer-node-title">{{ element?.name ?? '-' }} {{element?.category}}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="port port-in">
|
<div class="port port-in" magnet="active">
|
||||||
<div class="triangle-left" data-port="in-0" magnet="passive"></div>
|
<div class="triangle-left" data-port="in-0" magnet="passive"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full ks-designer-node-text">
|
<div class="w-full ks-designer-node-text">
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
{{ substring(element?.description ?? (element?.name ?? '-'), 40) }}
|
{{ substring(element?.description ?? (element?.name ?? '-'), 40) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="port port-out">
|
<div class="port port-out" magnet="active">
|
||||||
<div class="triangle-right" data-port="out-0" magnet="active"></div>
|
<div class="triangle-right" data-port="out-0" magnet="active"></div>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
@@ -190,7 +191,7 @@ export default defineComponent({
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 10px 30px !important;
|
padding: 10px 30px !important;
|
||||||
border-top: 1px solid rgba(108, 99, 255, 0.5);
|
//border-top: 1px solid rgba(108, 99, 255, 0.5);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -234,39 +235,42 @@ export default defineComponent({
|
|||||||
.triangle-left {
|
.triangle-left {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-top: 5px solid transparent;
|
border-top: 4px solid transparent;
|
||||||
border-right: 10px solid #3c82f6;
|
border-right: 5px solid #5da1df;
|
||||||
border-bottom: 6px solid transparent;
|
border-bottom: 4px solid transparent;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -8px;
|
left: -8px;
|
||||||
top: 2px;
|
top: 0.5px;
|
||||||
|
magnet: passive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 右三角形 */
|
/* 右三角形 */
|
||||||
.triangle-right {
|
.triangle-right {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-top: 5px solid transparent;
|
border-top: 4px solid transparent;
|
||||||
border-left: 10px solid #3c82f6;
|
border-left: 5px solid #5da1df;
|
||||||
border-bottom: 6px solid transparent;
|
border-bottom: 4px solid transparent;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -8px;
|
right: -8px;
|
||||||
top: 2px;
|
top: 0.5px;
|
||||||
|
magnet: passive;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 左侧入桩样式
|
// 左侧入桩样式
|
||||||
.port-in {
|
.port-in {
|
||||||
background-color: #6C63FF;
|
//background-color: #3c82f6;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
//border: 1px solid #093866;
|
//border: 1px solid #093866;
|
||||||
magnet: passive;
|
magnet: passive;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
width: 15px;
|
width: 13px;
|
||||||
height: 15px;
|
height: 13px;
|
||||||
display: block;
|
display: block;
|
||||||
background: url('@/assets/icons/point.svg') center / 100% 100%;
|
//background: url('@/assets/icons/point.svg') center / 100% 100%;
|
||||||
|
border: 2px solid #5da1df;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
//top: 7px;
|
//top: 7px;
|
||||||
@@ -279,10 +283,12 @@ export default defineComponent({
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
magnet: active;
|
magnet: active;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
width: 15px;
|
width: 13px;
|
||||||
height: 15px;
|
height: 13px;
|
||||||
display: block;
|
display: block;
|
||||||
background: url('@/assets/icons/point.svg') center / 100% 100%;
|
//background: url('@/assets/icons/point.svg') center / 100% 100%;
|
||||||
|
border: 2px solid #5da1df;
|
||||||
|
background:#5da1df;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
//right: 8px;
|
//right: 8px;
|
||||||
@@ -302,9 +308,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.ks-designer-root-node{
|
&.ks-designer-root-node{
|
||||||
.ant-card-head {
|
|
||||||
background: url('@/assets/icons/card-head-gray.png') center / 100% 100%;
|
|
||||||
}
|
|
||||||
.ks-designer-node-icon {
|
.ks-designer-node-icon {
|
||||||
background: url('@/assets/icons/icon-root.svg') center / 100% 100%;
|
background: url('@/assets/icons/icon-root.svg') center / 100% 100%;
|
||||||
}
|
}
|
||||||
@@ -320,32 +323,66 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.ks-designer-sequence-node{
|
&.ks-designer-sequence-node{
|
||||||
.ant-card-head {
|
|
||||||
background: url('@/assets/icons/card-head-green.png') center / 100% 100%;
|
|
||||||
}
|
|
||||||
.ks-designer-node-icon {
|
.ks-designer-node-icon {
|
||||||
background: url('@/assets/icons/icon-sequence.svg') center / 100% 100%;
|
background: url('@/assets/icons/icon-sequence.svg') center / 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ks-designer-parallel-node{
|
&.ks-designer-parallel-node{
|
||||||
.ant-card-head {
|
|
||||||
background: url('@/assets/icons/card-head-blue.png') center / 100% 100%;
|
|
||||||
}
|
|
||||||
.ks-designer-node-icon {
|
.ks-designer-node-icon {
|
||||||
background: url('@/assets/icons/icon-parallel.svg') center / 100% 100%;
|
background: url('@/assets/icons/icon-parallel.svg') center / 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ks-designer-precondition-node{
|
&.ks-designer-precondition-node{
|
||||||
.ant-card-head {
|
|
||||||
background: url('@/assets/icons/card-head-dark.png') center / 100% 100%;
|
|
||||||
}
|
|
||||||
.ks-designer-node-icon {
|
.ks-designer-node-icon {
|
||||||
background: url('@/assets/icons/icon-branch.svg') center / 100% 100%;
|
background: url('@/assets/icons/icon-branch.svg') center / 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.ks-designer-group-control,
|
||||||
|
&.ks-designer-group-condition {
|
||||||
|
.ant-card-head{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.ant-card-body {
|
||||||
|
height: calc(100%);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: url('@/assets/icons/card-head-gray.png') center / 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ks-designer-root-node{
|
||||||
|
.ant-card-body {
|
||||||
|
background: url('@/assets/icons/card-head-dark.png') center / 100% 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.ks-designer-sequence-node{
|
||||||
|
.ant-card-body {
|
||||||
|
background: url('@/assets/icons/card-head-green.png') center / 100% 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ks-designer-parallel-node{
|
||||||
|
.ant-card-body {
|
||||||
|
background: url('@/assets/icons/card-head-blue.png') center / 100% 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ks-designer-precondition-node{
|
||||||
|
.ant-card-body {
|
||||||
|
background: url('@/assets/icons/card-head-dark.png') center / 100% 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-in,
|
||||||
|
.port-out {
|
||||||
|
top: 40%;
|
||||||
|
}
|
||||||
|
.ks-designer-node-text{
|
||||||
|
line-height: 38px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//&.ks-designer-precondition-node{
|
//&.ks-designer-precondition-node{
|
||||||
// border:0;
|
// border:0;
|
||||||
// box-shadown:none;
|
// box-shadown:none;
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ export const createGraphTaskElement = (element: GraphTaskElement, width: number
|
|||||||
if (!realHeight) {
|
if (!realHeight) {
|
||||||
realHeight = 120;
|
realHeight = 120;
|
||||||
}
|
}
|
||||||
// if(element.category === 'precondition') {
|
if(element.group === 'condition' || element.group === 'control') {
|
||||||
// width = 100;
|
realHeight = 60;
|
||||||
// realHeight = 100;
|
}
|
||||||
// }
|
|
||||||
return {
|
return {
|
||||||
shape: 'task',
|
shape: 'task',
|
||||||
id: element.key,
|
id: element.key,
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ 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 Properties from './properties.vue';
|
import Properties from './properties.vue';
|
||||||
import type { BehaviorTree, NodeTemplate } from './types';
|
import type { BehaviorTree, 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';
|
||||||
@@ -106,7 +106,7 @@ export default defineComponent({
|
|||||||
const canvas = ref<HTMLDivElement | null>(null);
|
const canvas = ref<HTMLDivElement | null>(null);
|
||||||
const graph = ref<Graph | null>(null);
|
const graph = ref<Graph | null>(null);
|
||||||
const currentZoom = ref<number>(1);
|
const currentZoom = ref<number>(1);
|
||||||
const draggedNodeData = ref<NodeTemplate | 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 currentBehaviorTree = ref<BehaviorTree | null>(null);
|
||||||
@@ -127,7 +127,7 @@ export default defineComponent({
|
|||||||
} = useGraphCanvas();
|
} = useGraphCanvas();
|
||||||
|
|
||||||
// 处理拖动开始
|
// 处理拖动开始
|
||||||
const handleDragStart = (nm: NodeTemplate) => {
|
const handleDragStart = (nm: NodeDragTemplate) => {
|
||||||
draggedNodeData.value = nm;
|
draggedNodeData.value = nm;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取拖动的数据
|
// 获取拖动的数据
|
||||||
const template = draggedNodeData.value as NodeTemplate;
|
const template = draggedNodeData.value as NodeDragTemplate;
|
||||||
|
|
||||||
if (!hasElements(graph.value as Graph) && template.type !== 'root') {
|
if (!hasElements(graph.value as Graph) && template.type !== 'root') {
|
||||||
message.error('请先添加根节点.');
|
message.error('请先添加根节点.');
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
:data-type="nm.type"
|
:data-type="nm.type"
|
||||||
class="ks-model-drag-item"
|
class="ks-model-drag-item"
|
||||||
@dragend="handleDragEnd"
|
@dragend="handleDragEnd"
|
||||||
@dragstart="handleDragStart($event, nm)"
|
@dragstart="handleDragStart($event, nm, 'control')"
|
||||||
>
|
>
|
||||||
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
||||||
<span class="desc">{{ nm.name }}</span>
|
<span class="desc">{{ nm.name }}</span>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
:data-type="nm.type"
|
:data-type="nm.type"
|
||||||
class="ks-model-drag-item"
|
class="ks-model-drag-item"
|
||||||
@dragend="handleDragEnd"
|
@dragend="handleDragEnd"
|
||||||
@dragstart="handleDragStart($event, nm)"
|
@dragstart="handleDragStart($event, nm, 'condition')"
|
||||||
>
|
>
|
||||||
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
||||||
<span class="desc">{{ nm.name }}</span>
|
<span class="desc">{{ nm.name }}</span>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
:data-type="nm.type"
|
:data-type="nm.type"
|
||||||
class="ks-model-drag-item"
|
class="ks-model-drag-item"
|
||||||
@dragend="handleDragEnd"
|
@dragend="handleDragEnd"
|
||||||
@dragstart="handleDragStart($event, nm)"
|
@dragstart="handleDragStart($event, nm, 'action')"
|
||||||
>
|
>
|
||||||
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
<img :alt="nm.name ?? ''" class="icon" src="@/assets/icons/model-4.svg" />
|
||||||
<span class="desc">{{ nm.name }}</span>
|
<span class="desc">{{ nm.name }}</span>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, onMounted, ref } from 'vue';
|
import { defineComponent, onMounted, ref } from 'vue';
|
||||||
import type { NodeTemplate } from './types';
|
import type { NodeDragTemplate, NodeTemplate } from './types';
|
||||||
import { findNodeTemplates } from './api';
|
import { findNodeTemplates } from './api';
|
||||||
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
import { safePreventDefault, safeStopPropagation } from '@/utils/event';
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ export default defineComponent({
|
|||||||
const activeKey = ref<number>(1);
|
const activeKey = ref<number>(1);
|
||||||
const templateData = ref<NodeTemplate[]>([]);
|
const templateData = ref<NodeTemplate[]>([]);
|
||||||
const isDraggingOver = ref<boolean>(false);
|
const isDraggingOver = ref<boolean>(false);
|
||||||
const draggedNodeData = ref<NodeTemplate | null>(null);
|
const draggedNodeData = ref<NodeDragTemplate | null>(null);
|
||||||
// 控制节点
|
// 控制节点
|
||||||
const controlTemplates = ref<NodeTemplate[]>([]);
|
const controlTemplates = ref<NodeTemplate[]>([]);
|
||||||
// 条件节点
|
// 条件节点
|
||||||
@@ -111,15 +111,16 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDragStart = (e: DragEvent, nm: NodeTemplate) => {
|
const handleDragStart = (e: DragEvent, nm: NodeTemplate, group: String) => {
|
||||||
draggedNodeData.value = nm;
|
let dragNode: NodeDragTemplate = { ...nm, group: group };
|
||||||
|
draggedNodeData.value = dragNode as NodeDragTemplate;
|
||||||
|
|
||||||
if (e.dataTransfer) {
|
if (e.dataTransfer) {
|
||||||
e.dataTransfer.setData('text/plain', JSON.stringify(draggedNodeData.value));
|
e.dataTransfer.setData('text/plain', JSON.stringify(draggedNodeData.value));
|
||||||
e.dataTransfer.effectAllowed = 'copyMove';
|
e.dataTransfer.effectAllowed = 'copyMove';
|
||||||
|
|
||||||
const dragPreview = document.createElement('div');
|
const dragPreview = document.createElement('div');
|
||||||
dragPreview.textContent = draggedNodeData.value.name || '';
|
dragPreview.textContent = dragNode.name || '';
|
||||||
dragPreview.style.cssText = `
|
dragPreview.style.cssText = `
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -1000px;
|
top: -1000px;
|
||||||
@@ -132,8 +133,8 @@ export default defineComponent({
|
|||||||
`;
|
`;
|
||||||
document.body.appendChild(dragPreview);
|
document.body.appendChild(dragPreview);
|
||||||
e.dataTransfer.setDragImage(dragPreview, dragPreview.offsetWidth / 2, dragPreview.offsetHeight / 2);
|
e.dataTransfer.setDragImage(dragPreview, dragPreview.offsetWidth / 2, dragPreview.offsetHeight / 2);
|
||||||
emit('drag-item-start', nm, isDraggingOver.value, e);
|
emit('drag-item-start', dragNode, group, isDraggingOver.value, e);
|
||||||
console.log('开始拖动:', nm);
|
console.log('开始拖动:', dragNode);
|
||||||
setTimeout(() => document.body.removeChild(dragPreview), 0);
|
setTimeout(() => document.body.removeChild(dragPreview), 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ export interface NodeTemplate {
|
|||||||
parameters: ElementParameter[],
|
parameters: ElementParameter[],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NodeDragTemplate extends NodeTemplate {
|
||||||
|
group: String
|
||||||
|
}
|
||||||
|
|
||||||
export interface NodeTemplatesResponse extends ApiDataResponse<NodeTemplate[]> {
|
export interface NodeTemplatesResponse extends ApiDataResponse<NodeTemplate[]> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
* that was distributed with this source code.
|
* that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NodeTemplate } from '../types';
|
import type { NodeDragTemplate } from '../types';
|
||||||
import type { GraphTaskElement, GraphTaskRect } from '../builder/element';
|
import type { GraphTaskElement, GraphTaskRect } from '../builder/element';
|
||||||
import { generateKey } from '@/utils/strings';
|
import { generateKey } from '@/utils/strings';
|
||||||
|
|
||||||
export const createGraphTaskElementFromTemplate = (
|
export const createGraphTaskElementFromTemplate = (
|
||||||
template: NodeTemplate,
|
template: NodeDragTemplate,
|
||||||
rect?: GraphTaskRect,
|
rect?: GraphTaskRect,
|
||||||
): GraphTaskElement => {
|
): GraphTaskElement => {
|
||||||
let realRect = { width: 120, height: 80, x: 0, y: 0, ...rect || {} };
|
let realRect = { width: 120, height: 80, x: 0, y: 0, ...rect || {} };
|
||||||
@@ -25,6 +25,7 @@ export const createGraphTaskElementFromTemplate = (
|
|||||||
templateType: template.templateType,
|
templateType: template.templateType,
|
||||||
name: template.name,
|
name: template.name,
|
||||||
category: template.type,
|
category: template.type,
|
||||||
|
group: template.group,
|
||||||
description: template.description,
|
description: template.description,
|
||||||
order: 0,
|
order: 0,
|
||||||
position: {
|
position: {
|
||||||
|
|||||||
Reference in New Issue
Block a user