diff --git a/src/components/Canvas/FlowCanvas/components/header-tools.vue b/src/components/Canvas/FlowCanvas/components/header-tools.vue
index 10cffd2..7ef56c7 100644
--- a/src/components/Canvas/FlowCanvas/components/header-tools.vue
+++ b/src/components/Canvas/FlowCanvas/components/header-tools.vue
@@ -5,8 +5,8 @@
@@ -32,16 +32,36 @@
const stateManager = inject('stateManager') as any
const toolManager = inject('toolManager') as any
const tool = computed(() => stateManager.tool.value)
+ const historyIndex = computed(() => stateManager.historyIndex.value)
+ const historyList = computed(() => stateManager.historyList.value)
+ const isUndo = computed(() => !historyList.value[historyIndex.value - 1])
+ const isRedo = computed(() => !historyList.value[historyIndex.value + 1])
const tools = ref([
- { name: TOOLS.SELECT, icon: 'c-select', iconSize: 16 },
- { name: TOOLS.MOVE, icon: 'c-move', iconSize: 18 },
- { name: TOOLS.TEXT, icon: 'c-text', iconSize: 18 },
+ { name: TOOLS.SELECT, icon: 'c-select', iconSize: 16, disabled: ref(false) },
+ { name: TOOLS.MOVE, icon: 'c-move', iconSize: 18, disabled: ref(false) },
+ { name: TOOLS.TEXT, icon: 'c-text', iconSize: 18, disabled: ref(false) },
{ type: 'line' },
- { name: TOOLS.UNDO, icon: 'c-undo', iconSize: 18 },
- { name: TOOLS.REDO, icon: 'c-redo', iconSize: 18 }
+ {
+ name: TOOLS.UNDO,
+ icon: 'c-undo',
+ iconSize: 18,
+ disabled: isUndo,
+ on: () => stateManager.undoState()
+ },
+ {
+ name: TOOLS.REDO,
+ icon: 'c-redo',
+ iconSize: 18,
+ disabled: isRedo,
+ on: () => stateManager.redoState()
+ }
])
const onClickTool = (tool: any) => {
- toolManager.setTool(tool)
+ if (tool.on) {
+ tool.on()
+ } else {
+ toolManager.setTool(tool.name)
+ }
}
@@ -79,10 +99,14 @@
height: 3rem;
--svg-icon-color: #000;
border-radius: 0.4rem;
- &.active,
- &:hover {
+ &:not(.disabled).active,
+ &:not(.disabled):hover {
background-color: #dfdfdf;
}
+ &.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
}
> button {
width: 10rem;
diff --git a/src/components/Canvas/FlowCanvas/manager/StateManager.ts b/src/components/Canvas/FlowCanvas/manager/StateManager.ts
index 8cbb95b..049e844 100644
--- a/src/components/Canvas/FlowCanvas/manager/StateManager.ts
+++ b/src/components/Canvas/FlowCanvas/manager/StateManager.ts
@@ -16,9 +16,16 @@ export class StateManager {
zoom: any
tool: any
cursor: any
+ // 节点是否可拖动
nodesDraggable: any
+ // 拖动时是否可以平移画布
panOnDrag: any
+ // 历史记录-撤回/重做
+ mxHistory: any
+ historyList: any
+ historyIndex: any
+
// 管理器
eventManager: any
flowManager: any
@@ -38,17 +45,14 @@ export class StateManager {
this.cursor = ref("")
this.nodesDraggable = ref(false)
this.panOnDrag = ref(false)
+ this.mxHistory = ref(50)
+ this.historyList = ref([])
+ this.historyIndex = ref(0)
+
this.nodes = ref([]);
this.nodes_ = computed(() => {
return this.nodes.value.map((node, index) => {
const obj = node;
- // if (index === 0) {
- // obj.type = NODE_TYPE.INPUT;
- // } else if (index === this.nodes.value.length - 1) {
- // obj.type = NODE_TYPE.OUTPUT;
- // } else {
- // obj.type = NODE_TYPE.SECONDARY;
- // }
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)
@@ -68,17 +72,6 @@ export class StateManager {
this.edges = computed(() => {
const arr = []
this.nodes.value.forEach((node, index) => {
- // if (index < this.nodes.value.length - 1) {
- // const source = node.id
- // const target = this.nodes.value[index + 1].id
- // arr.push({
- // id: `el-${source}-${target}`,
- // source: source,
- // target: target,
- // selectable: false,
- // type: 'default'
- // })
- // }
const superiorID = node.data.superiorID;
const isSuperior = this.nodes.value.some((v) => v.id === superiorID)
if (superiorID && isSuperior) {
@@ -99,28 +92,21 @@ export class StateManager {
}
/** 添加节点 */
addNode(node: NodesItem) {
- this.nodes.value.push(node)
+ this.nodes.value.push(node);
+ this.recordState()
}
/** 删除节点 */
deleteNode(id: string) {
this.nodes.value = this.nodes.value.filter((node: NodesItem) => node.id !== id)
+ this.recordState()
}
/** 获取节点 */
- getNodeById(id: string) {
- return this.nodes.value.find((node: NodesItem) => node.id === id)
- }
+ getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
/** 获取下级节点 */
- getSubordNodeByID(id: string) {
- return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id)
- }
- getLastNode() {
- return this.nodes.value[this.nodes.value.length - 1]
- }
+ getSubordNodeByID(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
+ getLastNode() { return this.nodes.value[this.nodes.value.length - 1] }
/** 设置工具 */
- setTool(tool: string) {
- this.tool.value = tool
- }
-
+ setTool(tool: string) { this.tool.value = tool }
/** 设置光标 */
setCursor(v: string) { this.cursor.value = v }
/** 设置节点是否可拖动 */
@@ -128,11 +114,38 @@ export class StateManager {
/** 设置是否可以平移画布 */
setPanOnDrag(v: boolean) { this.panOnDrag.value = v }
/** 获取节点最大zIndex值 */
- getMaxZIndex() {
- return this.nodes.value.reduce((max, node) => Math.max(max, node.zIndex), 0)
- }
+ getMaxZIndex() { return this.nodes.value.reduce((max, node) => Math.max(max, node.zIndex), 0) }
/** 获取节点最小zIndex值 */
- getMinZIndex() {
- return this.nodes.value.reduce((min, node) => Math.min(min, node.zIndex), 0)
+ getMinZIndex() { return this.nodes.value.reduce((min, node) => Math.min(min, node.zIndex), 0) }
+
+ /** 记录状态 */
+ recordState() {
+ if (this.historyIndex.value < this.historyList.value.length - 1) {
+ this.historyList.value.splice(this.historyIndex.value)
+ }
+ const state = {
+ nodes: JSON.stringify(this.nodes.value)
+ }
+ this.historyList.value.push(state)
+ const size = this.historyList.value.length - this.mxHistory.value
+ if (size > 0) this.historyList.value.splice(0, size)
+ this.historyIndex.value = this.historyList.value.length - 1
}
+ /** 撤回状态 */
+ undoState() {
+ var index = this.historyIndex.value - 1
+ const state = this.historyList.value[index]
+ if (!state) return
+ this.historyIndex.value = index
+ this.nodes.value = JSON.parse(state.nodes)
+ }
+ /** 重做状态 */
+ redoState() {
+ var index = this.historyIndex.value + 1
+ const state = this.historyList.value[index]
+ if (!state) return
+ this.historyIndex.value = index
+ this.nodes.value = JSON.parse(state.nodes)
+ }
+
}