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

244 lines
7.6 KiB
TypeScript
Raw Normal View History

2026-02-26 11:45:32 +08:00
import { ref, computed } from "vue";
2026-03-12 17:07:04 +08:00
import { NODE_TYPE, NODE_DATATYPE } 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'
import { putSketchFlowCanvas } from '@/api/flow-canvas'
2026-03-05 15:59:04 +08:00
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-03-12 17:07:04 +08:00
generateManager: any
2026-03-17 11:06:32 +08:00
// 保存画布数据定时器
saveCanvasTime: any
// 保存画布数据定时器时间间隔
saveCanvasTimeInterval: any
// 打开画布线稿id
sketchId: 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-03-12 17:07:04 +08:00
options.generateManager && (this.generateManager = options.generateManager)
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)
this.sketchId = options.sketchId
this.saveCanvasTimeInterval = 6000
this.saveCanvasTime = null
2026-03-05 10:18:10 +08:00
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-12 17:07:04 +08:00
visible: (node.data.type !== NODE_DATATYPE.RESULT_IMAGE || node.data.isActive),
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()
this.exportFlow()
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()
this.exportFlow()
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-13 11:24:29 +08:00
getSubordNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
2026-03-12 17:07:04 +08:00
getLastNode() { console.log(this.nodes.value); 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-13 13:49:07 +08:00
/** 获取所有下级节点 */
getSubordNodes(id: string) { return this.nodes.value.filter((node: NodesItem) => node.data.superiorID === id) }
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
}
/** 画布数据存储 */
async exportFlow (time:number = 0){
if(!this.sketchId)return
clearTimeout(this.saveCanvasTime)
await new Promise((resolve) => {
this.saveCanvasTime = setTimeout(()=>{
putSketchFlowCanvas({
id: this.sketchId,
canvasData: JSON.stringify(this.nodes.value) }).then(() => {
resolve(true)
}).catch(() => {
resolve(true)
})
},time)
})
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)
this.exportFlow(this.saveCanvasTimeInterval)
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)
this.exportFlow(this.saveCanvasTimeInterval)
2026-03-05 10:18:10 +08:00
}
2026-03-12 17:07:04 +08:00
/** 显示指定子节点和父节点连接线,隐藏父节点和其他子节点链接线, */
showNodeConnections(id: string) {
const node = this.getNodeById(id)
if(node.data.component != NODE_DATATYPE.RESULT_IMAGE && node.data.superiorID) return
let edges_ = JSON.parse(JSON.stringify(this.edges.value))
this.nodes.value.forEach((nodeItem) => {
if(node.data.superiorID === nodeItem.data.superiorID && nodeItem.id == id) {
nodeItem.data.isActive = true
}else if(node.data.superiorID == nodeItem.data.superiorID){
nodeItem.data.isActive = false
}
})
}
2026-03-11 17:02:32 +08:00
dispose() {
clearTimeout(this.saveCanvasTime)
2026-03-11 17:02:32 +08:00
this.historyList.value = []
this.historyIndex.value = 0
}
2026-02-26 11:45:32 +08:00
}