diff --git a/src/assets/icons/c-hand.svg b/src/assets/icons/c-move.svg
similarity index 100%
rename from src/assets/icons/c-hand.svg
rename to src/assets/icons/c-move.svg
diff --git a/src/assets/icons/c-mouse.svg b/src/assets/icons/c-select.svg
similarity index 100%
rename from src/assets/icons/c-mouse.svg
rename to src/assets/icons/c-select.svg
diff --git a/src/assets/icons/c-t.svg b/src/assets/icons/c-text.svg
similarity index 100%
rename from src/assets/icons/c-t.svg
rename to src/assets/icons/c-text.svg
diff --git a/src/components/Canvas/FlowCanvas/components/header-tools.vue b/src/components/Canvas/FlowCanvas/components/header-tools.vue
index 51dc905..10cffd2 100644
--- a/src/components/Canvas/FlowCanvas/components/header-tools.vue
+++ b/src/components/Canvas/FlowCanvas/components/header-tools.vue
@@ -1,29 +1,48 @@
diff --git a/src/components/Canvas/FlowCanvas/components/cards/add-print.vue b/src/components/Canvas/FlowCanvas/components/nodes/cards/add-print.vue
similarity index 88%
rename from src/components/Canvas/FlowCanvas/components/cards/add-print.vue
rename to src/components/Canvas/FlowCanvas/components/nodes/cards/add-print.vue
index 34b1ac2..2f9f257 100644
--- a/src/components/Canvas/FlowCanvas/components/cards/add-print.vue
+++ b/src/components/Canvas/FlowCanvas/components/nodes/cards/add-print.vue
@@ -59,11 +59,11 @@
+
+
diff --git a/src/components/Canvas/FlowCanvas/flow-canvas.vue b/src/components/Canvas/FlowCanvas/flow-canvas.vue
index 08f607d..030923f 100644
--- a/src/components/Canvas/FlowCanvas/flow-canvas.vue
+++ b/src/components/Canvas/FlowCanvas/flow-canvas.vue
@@ -6,18 +6,32 @@
:edges="edges"
:min-zoom="0.1"
:max-zoom="10"
- :nodes-draggable="true"
+ :nodes-draggable="nodesDraggable"
+ :pan-on-drag="panOnDrag"
@nodes-initialized="layoutGraph('LR')"
@node-drag-stop="(e) => eventManager.handleNodeDragStop(e)"
@viewport-change="(e) => eventManager.handleViewportChange(e)"
+ @pane-click="(e) => eventManager.handleClick(e)"
+ :class="{ 'custom-cursor': !!stateManager.cursor.value }"
+ :style="{ '--custom-cursor': stateManager.cursor.value }"
>
-
-
+
+
@@ -44,11 +58,13 @@
import zoom from '../components/zoom.vue'
// 节点
import node from './components/node.vue'
- import resultImage from './components/result/result-image.vue'
- import card from './components/cards/index.vue'
+ import resultImage from './components/nodes/result-image.vue'
+ import card from './components/nodes/cards/index.vue'
+ import text from './components/nodes/text.vue'
const components = {
[NODE_COMPONENT.RESULT_IMAGE]: resultImage,
- [NODE_COMPONENT.CARD]: card
+ [NODE_COMPONENT.CARD]: card,
+ [NODE_COMPONENT.TEXT]: text
}
// 管理器
@@ -56,6 +72,7 @@
import { EventManager } from './manager/EventManager'
import { FlowManager } from './manager/FlowManager'
import { NodeManager } from './manager/NodeManager'
+ import { ToolManager, TOOLS } from './manager/ToolManager'
const props = defineProps({
config: {
@@ -65,29 +82,36 @@
})
const vueFlow = ref()
- const nodeTypes = ref([NODE_TYPE.INPUT, NODE_TYPE.SECONDARY, NODE_TYPE.OUTPUT])
+ const nodeTypes = ref([NODE_TYPE.INPUT, NODE_TYPE.SECONDARY, NODE_TYPE.OUTPUT, NODE_TYPE.ALONE])
// 状态管理器
const stateManager = new StateManager({ vueFlow })
- const nodes = computed(() => stateManager.nodes_.value)
- const edges = computed(() => stateManager.edges.value)
+ provide('stateManager', stateManager)
+
// 事件管理器
const eventManager = new EventManager({ stateManager, vueFlow })
+ stateManager.setManager({ eventManager })
+ provide('eventManager', eventManager)
+
// 流程管理器
const flowManager = new FlowManager({ stateManager, vueFlow })
+ stateManager.setManager({ flowManager })
+ provide('flowManager', flowManager)
+
// 节点管理器
const nodeManager = new NodeManager({ stateManager, vueFlow })
- stateManager.setManager({
- eventManager,
- flowManager,
- nodeManager
- })
+ stateManager.setManager({ nodeManager })
+ provide('nodeManager', nodeManager)
- provide('stateManager', stateManager)
- provide('eventManager', eventManager)
- provide('flowManager', flowManager)
- provide('nodeManager', nodeManager)
- provide('nodeManager', nodeManager)
+ // 工具管理器
+ const toolManager = new ToolManager({ stateManager, vueFlow })
+ stateManager.setManager({ toolManager })
+ provide('toolManager', toolManager)
+
+ const nodes = computed(() => stateManager.nodes_.value)
+ const edges = computed(() => stateManager.edges.value)
+ const nodesDraggable = computed(() => stateManager.nodesDraggable.value)
+ const panOnDrag = computed(() => stateManager.panOnDrag.value)
const { fitView } = useVueFlow()
const { layout } = useLayout()
@@ -107,6 +131,15 @@
}, 0)
}
+ /** 删除节点 */
+ const deleteNode = (id) => {
+ nodeManager.deleteNode(id)
+ }
+ /** 复制节点 */
+ const copyNode = (id) => {
+ console.log('复制:', id)
+ }
+
// 导出流程
const exportFlow = () => {
// flowManager.exportFlow()
@@ -156,6 +189,9 @@
> .vue-flow {
width: 100%;
height: 100%;
+ &.custom-cursor {
+ cursor: var(--custom-cursor, pointer);
+ }
}
}
diff --git a/src/components/Canvas/FlowCanvas/manager/EventManager.ts b/src/components/Canvas/FlowCanvas/manager/EventManager.ts
index 390ece3..a7135e8 100644
--- a/src/components/Canvas/FlowCanvas/manager/EventManager.ts
+++ b/src/components/Canvas/FlowCanvas/manager/EventManager.ts
@@ -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)
+ }
+ }
}
diff --git a/src/components/Canvas/FlowCanvas/manager/NodeManager.ts b/src/components/Canvas/FlowCanvas/manager/NodeManager.ts
index c5cde46..242d4c1 100644
--- a/src/components/Canvas/FlowCanvas/manager/NodeManager.ts
+++ b/src/components/Canvas/FlowCanvas/manager/NodeManager.ts
@@ -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_)
}
diff --git a/src/components/Canvas/FlowCanvas/manager/StateManager.ts b/src/components/Canvas/FlowCanvas/manager/StateManager.ts
index 5db7102..cd50557 100644
--- a/src/components/Canvas/FlowCanvas/manager/StateManager.ts
+++ b/src/components/Canvas/FlowCanvas/manager/StateManager.ts
@@ -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([]);
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 }
}
diff --git a/src/components/Canvas/FlowCanvas/manager/ToolManager.ts b/src/components/Canvas/FlowCanvas/manager/ToolManager.ts
new file mode 100644
index 0000000..7638bbc
--- /dev/null
+++ b/src/components/Canvas/FlowCanvas/manager/ToolManager.ts
@@ -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 || "")
+ }
+
+}
diff --git a/src/components/Canvas/FlowCanvas/tools/index.d.ts b/src/components/Canvas/FlowCanvas/tools/index.d.ts
index ac7d26f..49c4d93 100644
--- a/src/components/Canvas/FlowCanvas/tools/index.d.ts
+++ b/src/components/Canvas/FlowCanvas/tools/index.d.ts
@@ -4,6 +4,7 @@
export const NODE_COMPONENT = {
RESULT_IMAGE: 'result-image',
CARD: 'card',
+ TEXT: 'text',
}
/**
@@ -13,6 +14,7 @@ export const NODE_TYPE = {
INPUT: 'InputNode',
SECONDARY: 'SecondaryNode',
OUTPUT: 'OutputNode',
+ ALONE: 'AloneNode',
}
/**
diff --git a/src/lang/en.ts b/src/lang/en.ts
index dd27aa1..4e60e98 100644
--- a/src/lang/en.ts
+++ b/src/lang/en.ts
@@ -64,7 +64,7 @@ export default {
rename: 'Rename',
delete: 'Delete',
setting: 'Setting',
- logout: 'Logout',
+ logout: 'Log out',
general: 'General',
profile: 'Profile',
learnMore: 'Learn More',
diff --git a/src/views/home/setting/General.vue b/src/views/home/setting/General.vue
index 328190a..0764044 100644
--- a/src/views/home/setting/General.vue
+++ b/src/views/home/setting/General.vue
@@ -46,12 +46,12 @@
diff --git a/src/views/home/setting/LearnMore.vue b/src/views/home/setting/LearnMore.vue
index 801b222..ebf432e 100644
--- a/src/views/home/setting/LearnMore.vue
+++ b/src/views/home/setting/LearnMore.vue
@@ -22,12 +22,12 @@
diff --git a/src/views/home/setting/index.vue b/src/views/home/setting/index.vue
index 34d7399..c7087b0 100644
--- a/src/views/home/setting/index.vue
+++ b/src/views/home/setting/index.vue
@@ -11,7 +11,7 @@