Files
FiDA_Front/src/components/Canvas/FlowCanvas/manager/StateManager.ts

191 lines
5.8 KiB
TypeScript
Raw Normal View History

2026-02-26 11:45:32 +08:00
import { ref, computed } from "vue";
2026-02-27 14:58:36 +08:00
import { NODE_TYPE } from '../tools/index.d'
2026-03-05 15:13:16 +08:00
import { ElMessageBox } from 'element-plus'
2026-03-05 15:59:04 +08:00
import i18n from '@/lang'
const t = i18n.global.t
2026-02-26 11:45:32 +08:00
2026-02-27 14:58:36 +08:00
export interface NodesItem {
id: string
type: string
class: string
position: { x: number, y: number }
2026-03-05 10:38:33 +08:00
data: { component: any, type: string, superiorID?: string }
2026-02-27 14:58:36 +08:00
}
2026-02-26 11:45:32 +08:00
export class StateManager {
vueFlow: any
2026-03-05 13:46:10 +08:00
activeNodeID: any
2026-02-26 11:45:32 +08:00
nodes: any
2026-02-27 11:43:27 +08:00
nodes_: any
2026-02-26 11:45:32 +08:00
edges: any
zoom: any
2026-03-04 15:06:22 +08:00
tool: any
cursor: any
2026-03-05 10:18:10 +08:00
// 节点是否可拖动
2026-03-04 15:06:22 +08:00
nodesDraggable: any
2026-03-05 10:18:10 +08:00
// 拖动时是否可以平移画布
2026-03-04 15:06:22 +08:00
panOnDrag: any
2026-03-05 10:18:10 +08:00
// 历史记录-撤回/重做
mxHistory: any
historyList: any
historyIndex: any
2026-03-04 15:06:22 +08:00
// 管理器
2026-02-27 09:56:49 +08:00
eventManager: any
flowManager: any
nodeManager: any
2026-03-04 15:06:22 +08:00
toolManager: any
2026-02-27 09:56:49 +08:00
// 设置管理器
setManager(options) {
options.eventManager && (this.eventManager = options.eventManager)
options.flowManager && (this.flowManager = options.flowManager)
options.nodeManager && (this.nodeManager = options.nodeManager)
2026-03-04 15:06:22 +08:00
options.toolManager && (this.toolManager = options.toolManager)
2026-02-27 09:56:49 +08:00
}
2026-02-26 11:45:32 +08:00
constructor(options) {
this.vueFlow = options.vueFlow
2026-03-03 11:10:43 +08:00
this.zoom = ref(1)
2026-03-04 15:06:22 +08:00
this.tool = ref("")
this.cursor = ref("")
this.nodesDraggable = ref(false)
this.panOnDrag = ref(false)
2026-03-05 10:18:10 +08:00
this.mxHistory = ref(50)
this.historyList = ref([])
this.historyIndex = ref(0)
2026-03-05 13:46:10 +08:00
this.activeNodeID = ref("")
2026-02-27 14:58:36 +08:00
this.nodes = ref<NodesItem[]>([]);
2026-02-27 11:43:27 +08:00
this.nodes_ = computed(() => {
return this.nodes.value.map((node, index) => {
2026-03-03 15:39:54 +08:00
const obj = node;
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)
2026-03-04 15:06:22 +08:00
if (!isSuperior && isSubord) {// 没有上级 有下级
2026-02-27 14:58:36 +08:00
obj.type = NODE_TYPE.INPUT;
2026-03-04 15:06:22 +08:00
} else if (isSuperior && isSubord) {// 有上级 有下级
2026-02-27 14:58:36 +08:00
obj.type = NODE_TYPE.SECONDARY;
2026-03-04 15:06:22 +08:00
} else if (isSuperior && !isSubord) {// 有上级 没有下级
2026-03-03 15:39:54 +08:00
obj.type = NODE_TYPE.OUTPUT;
2026-03-04 15:06:22 +08:00
} else {// 其他情况-没有上级 没有下级
obj.type = NODE_TYPE.ALONE;
2026-02-27 11:43:27 +08:00
}
return obj
})
})
2026-02-26 11:45:32 +08:00
this.edges = computed(() => {
const arr = []
this.nodes.value.forEach((node, index) => {
2026-03-03 15:39:54 +08:00
const superiorID = node.data.superiorID;
const isSuperior = this.nodes.value.some((v) => v.id === superiorID)
if (superiorID && isSuperior) {
const source = node.data.superiorID
const target = node.id
2026-02-26 11:45:32 +08:00
arr.push({
2026-03-03 15:39:54 +08:00
id: `el-${source}-${target}`,
source: source,
2026-02-26 11:45:32 +08:00
target: target,
2026-03-02 16:24:32 +08:00
selectable: false,
2026-03-02 13:51:14 +08:00
type: 'default'
2026-02-26 11:45:32 +08:00
})
}
})
return arr
})
}
2026-03-05 13:46:10 +08:00
/** 设置激活节点 */
setActiveNodeID(id: string) { this.activeNodeID.value = id }
2026-02-27 14:58:36 +08:00
/** 添加节点 */
addNode(node: NodesItem) {
2026-03-05 10:18:10 +08:00
this.nodes.value.push(node);
this.recordState()
2026-02-27 14:58:36 +08:00
}
/** 删除节点 */
2026-03-05 15:59:04 +08:00
async deleteNode(id: string, { isElMessageBox } = { isElMessageBox: false }) {
2026-03-05 16:56:03 +08:00
const node = this.getNodeById(id)
if (!node) return console.warn(`没有找到指定id:${id}`)
if (node.data.disableDelete) return console.warn('该节点禁用删除')
2026-03-05 15:59:04 +08:00
let deletePromise: any = true
if (isElMessageBox) {
2026-03-05 15:13:16 +08:00
deletePromise = await new Promise<void>((resolve, reject) => {
ElMessageBox.confirm(
2026-03-05 15:59:04 +08:00
t('flowCanvas.deleteCardConfirm'),
2026-03-05 15:13:16 +08:00
'',
{
2026-03-05 15:59:04 +08:00
confirmButtonText: t('flowCanvas.confirm'),
cancelButtonText: t('flowCanvas.cancel'),
2026-03-05 15:13:16 +08:00
}
).then(() => {
resolve(true)
}).catch(() => {
resolve(false)
})
})
}
if (!deletePromise) return console.log('删除操作被取消')
2026-02-27 14:58:36 +08:00
this.nodes.value = this.nodes.value.filter((node: NodesItem) => node.id !== id)
2026-03-05 10:18:10 +08:00
this.recordState()
2026-02-27 14:58:36 +08:00
}
2026-03-03 16:16:30 +08:00
/** 获取节点 */
2026-03-05 10:18:10 +08:00
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
2026-03-03 16:16:30 +08:00
/** 获取下级节点 */
2026-03-05 10:18:10 +08:00
getSubordNodeByID(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
getLastNode() { return this.nodes.value[this.nodes.value.length - 1] }
2026-03-04 15:06:22 +08:00
/** 设置工具 */
2026-03-05 10:18:10 +08:00
setTool(tool: string) { this.tool.value = tool }
2026-03-04 15:06:22 +08:00
/** 设置光标 */
setCursor(v: string) { this.cursor.value = v }
/** 设置节点是否可拖动 */
setNodesDraggable(v: boolean) { this.nodesDraggable.value = v }
/** 设置是否可以平移画布 */
setPanOnDrag(v: boolean) { this.panOnDrag.value = v }
2026-03-05 10:27:41 +08:00
/** 设置节点层级至最顶部 */
bringToFont(id) {
const fromIndex = this.nodes.value.findIndex(item => item.id === id)
if (fromIndex === -1) return console.warn(`没有找到指定id:${id}`)
this.nodes.value.splice(this.nodes.value.length - 1, 0, ...this.nodes.value.splice(fromIndex, 1))
2026-03-04 15:40:30 +08:00
}
2026-03-05 10:27:41 +08:00
/** 设置节点层级至最低部 */
sendToBack(id) {
const fromIndex = this.nodes.value.findIndex(item => item.id === id)
if (fromIndex === -1) return console.warn(`没有找到指定id:${id}`)
this.nodes.value.splice(0, 0, ...this.nodes.value.splice(fromIndex, 1))
}
2026-03-05 10:18:10 +08:00
/** 记录状态 */
recordState() {
if (this.historyIndex.value < this.historyList.value.length - 1) {
2026-03-05 14:34:41 +08:00
this.historyList.value.splice(this.historyIndex.value + 1)
2026-03-05 10:18:10 +08:00
}
const state = {
nodes: JSON.stringify(this.nodes.value)
2026-03-05 10:27:41 +08:00
}
2026-03-05 10:18:10 +08:00
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
2026-03-04 15:40:30 +08:00
}
2026-03-05 10:18:10 +08:00
/** 撤回状态 */
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)
2026-03-04 15:40:30 +08:00
}
2026-03-05 10:18:10 +08:00
/** 重做状态 */
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)
}
2026-03-11 17:02:32 +08:00
dispose() {
this.historyList.value = []
this.historyIndex.value = 0
}
2026-02-26 11:45:32 +08:00
}