This commit is contained in:
lzp
2026-03-04 15:06:22 +08:00
parent 9817e5e0db
commit cee42d8b78
28 changed files with 340 additions and 84 deletions

View File

@@ -1,3 +1,4 @@
import { TOOLS } from "./ToolManager"
export class EventManager {
stateManager: any
vueFlow: any
@@ -7,10 +8,12 @@ export class EventManager {
this.vueFlow = options.vueFlow
this.zoom = this.stateManager.zoom
}
/** 处理视口变化 */
handleViewportChange(e: any) {
const { zoom } = e
this.zoom.value = zoom
}
/** 处理节点拖动停止 */
handleNodeDragStop(e: any) {
const { node } = e
const { id, position } = node
@@ -21,4 +24,17 @@ export class EventManager {
}
})
}
/** 处理点击 */
handleClick(event: any) {
const tool = this.stateManager.tool.value
if (tool === TOOLS.TEXT) {
const { x, y, zoom } = this.vueFlow.value.viewport
const position = {
x: (event.offsetX - x) / zoom,
y: (event.offsetY - y) / zoom
}
this.stateManager.nodeManager.createTextNode({ position })
this.stateManager.toolManager.setTool(TOOLS.SELECT)
}
}
}

View File

@@ -1,5 +1,5 @@
import { createId } from '../../tools/tools'
import { NODE_DATATYPE, NODE_COMPONENT } from '../tools/index.d'
import { NODE_DATATYPE, NODE_COMPONENT, NODE_DATATIER } from '../tools/index.d'
interface NodeOptions {
id?: string
position?: { x: number, y: number }
@@ -34,11 +34,12 @@ export class NodeManager {
const positionX = options.positionX || 0
const positionY = options.positionY || 0
const position = options.position ||
!snode ? { x: positionX, y: positionY } :
{
x: snode.position.x + snode.dimensions.width + 50 + positionX,
y: snode.position.y + positionY
}
(!snode ?
{ x: positionX, y: positionY } :
{
x: snode.position.x + snode.dimensions.width + 50 + positionX,
y: snode.position.y + positionY
})
const data = options?.data || {}
data['component'] = options.component
const options_ = {
@@ -55,7 +56,7 @@ export class NodeManager {
...(options ? options : {}),
component: NODE_COMPONENT.RESULT_IMAGE,
data: {
tier: 0,
tier: NODE_DATATIER.RESULT_IMAGE,
type: NODE_DATATYPE.RESULT_IMAGE,
isHeader: true,
...(options?.data || {}),
@@ -70,7 +71,7 @@ export class NodeManager {
component: NODE_COMPONENT.CARD,
positionY: 50,
data: {
tier: 1,
tier: NODE_DATATIER.CARDS_SELECT,
type: NODE_DATATYPE.CARDS_SELECT,
...(options?.data || {}),
},
@@ -82,6 +83,20 @@ export class NodeManager {
const options_ = {
...(options ? options : {}),
component: NODE_COMPONENT.CARD,
data: {
...(options?.data || {}),
}
}
return this.createNode(options_)
}
/** 创建文本节点 */
createTextNode(options?: NodeOptions) {
const options_ = {
...(options ? options : {}),
component: NODE_COMPONENT.TEXT,
data: {
...(options?.data || {}),
}
}
return this.createNode(options_)
}

View File

@@ -14,19 +14,30 @@ export class StateManager {
nodes_: any
edges: any
zoom: any
// 管理器
tool: any
cursor: any
nodesDraggable: any
panOnDrag: any
// 管理器
eventManager: any
flowManager: any
nodeManager: any
toolManager: any
// 设置管理器
setManager(options) {
options.eventManager && (this.eventManager = options.eventManager)
options.flowManager && (this.flowManager = options.flowManager)
options.nodeManager && (this.nodeManager = options.nodeManager)
options.toolManager && (this.toolManager = options.toolManager)
}
constructor(options) {
this.vueFlow = options.vueFlow
this.zoom = ref(1)
this.tool = ref("")
this.cursor = ref("")
this.nodesDraggable = ref(false)
this.panOnDrag = ref(false)
this.nodes = ref<NodesItem[]>([]);
this.nodes_ = computed(() => {
return this.nodes.value.map((node, index) => {
@@ -41,14 +52,14 @@ export class StateManager {
const superiorID = node.data.superiorID;
const isSuperior = this.nodes.value.some((v) => v.id === superiorID)
const isSubord = this.nodes.value.some((v) => v.data.superiorID === node.id)
if (!superiorID) {// 没有上级ID
if (!isSuperior && isSubord) {// 没有上级 有下级
obj.type = NODE_TYPE.INPUT;
} else if (isSuperior && isSubord) {// 有上级ID并找到下级
} else if (isSuperior && isSubord) {// 有上级下级
obj.type = NODE_TYPE.SECONDARY;
} else if (isSuperior && !isSubord) {// 有上级ID但未找到下级
} else if (isSuperior && !isSubord) {// 有上级 没有下级
obj.type = NODE_TYPE.OUTPUT;
} else {// 其他情况-有上级ID未找到上
obj.type = NODE_TYPE.INPUT;
} else {// 其他情况-有上级 没有下
obj.type = NODE_TYPE.ALONE;
}
return obj
})
@@ -105,4 +116,15 @@ export class StateManager {
getLastNode() {
return this.nodes.value[this.nodes.value.length - 1]
}
/** 设置工具 */
setTool(tool: string) {
this.tool.value = tool
}
/** 设置光标 */
setCursor(v: string) { this.cursor.value = v }
/** 设置节点是否可拖动 */
setNodesDraggable(v: boolean) { this.nodesDraggable.value = v }
/** 设置是否可以平移画布 */
setPanOnDrag(v: boolean) { this.panOnDrag.value = v }
}

View File

@@ -0,0 +1,47 @@
export const TOOLS = {
SELECT: "SELECT",
MOVE: "MOVE",
TEXT: "TEXT",
UNDO: "UNDO",
REDO: "REDO",
}
export const tools = [
/** 选择工具 */
{
name: TOOLS.SELECT,
nodesDraggable: true,
panOnDrag: false,
},
/** 移动工具 */
{
name: TOOLS.MOVE,
nodesDraggable: false,
panOnDrag: true,
},
/** 文本工具 */
{
name: TOOLS.TEXT,
cursor: "text",
nodesDraggable: false,
panOnDrag: false,
},
]
export class ToolManager {
stateManager: any
vueFlow: any
constructor(options) {
this.stateManager = options.stateManager;
this.vueFlow = options.vueFlow
this.setTool(TOOLS.SELECT)
}
setTool(value: string) {
const tool = tools.find((t) => t.name === value)
if (!tool) return console.warn(`工具${tool}不存在`)
this.stateManager.tool.value = tool.name
this.stateManager.setNodesDraggable(!!tool.nodesDraggable)
this.stateManager.setPanOnDrag(!!tool.panOnDrag)
this.stateManager.setCursor(tool.cursor || "")
}
}