import { ref, computed } from "vue"; import { NODE_TYPE, NODE_DATATYPE } from '../tools/index.d' import { ElMessageBox } from 'element-plus' import i18n from '@/lang' import { putSketchFlowCanvas } from '@/api/flow-canvas' import myEvent from '@/utils/myEvent' const t = i18n.global.t //推送到对话框的助手 const chatAssistant = { [NODE_DATATYPE.TO_REAL_STYLE]:{ content: t('FlowCanvas.toRealStyleDesignAssistant'), nodeType:NODE_DATATYPE.TO_REAL_STYLE, }, [NODE_DATATYPE.CANVAS_MODE]:{ content: t('FlowCanvas.surfaceEditCanvasDesignAssistant'), nodeType:NODE_DATATYPE.CANVAS_MODE, }, [NODE_DATATYPE.Fast_MODE]:{ content: t('FlowCanvas.surfaceEditAIDesignAssistant'), nodeType:NODE_DATATYPE.Fast_MODE, }, [NODE_DATATYPE.COLOR_PALETTE]:{ content: t('FlowCanvas.colorPaletteDesignAssistant'), nodeType:NODE_DATATYPE.COLOR_PALETTE, }, [NODE_DATATYPE.SCENE_COMPOSITION]:{ content: t('FlowCanvas.sceneCompositionDesignAssistant'), nodeType:NODE_DATATYPE.SCENE_COMPOSITION, }, [NODE_DATATYPE.TO_3D_MODEL]:{ content: t('FlowCanvas.threeModelDesignAssistant'), nodeType:NODE_DATATYPE.TO_3D_MODEL, }, [NODE_DATATYPE.TO_REAL_VARIANTS]:{ content: t('FlowCanvas.toRealVariantsDesignAssistant'), nodeType:NODE_DATATYPE.TO_3D_MODEL, }, [NODE_DATATYPE.TO_3VIEW]:{ content: t('FlowCanvas.to3DViewDesignAssistant'), nodeType:NODE_DATATYPE.TO_3VIEW, }, } export interface NodesItem { id: string type: string class: string position: { x: number, y: number } data: { component: any, type: string, superiorID?: string } } export class StateManager { vueFlow: any activeNodeID: any nodes: any nodes_: any edges: any zoom: any tool: any cursor: any // 节点是否可拖动 nodesDraggable: any // 拖动时是否可以平移画布 panOnDrag: any // 历史记录-撤回/重做 mxHistory: any historyList: any historyIndex: any // 管理器 eventManager: any flowManager: any nodeManager: any toolManager: any generateManager: any // 保存画布数据定时器 saveCanvasTime: any // 保存画布数据定时器时间间隔 saveCanvasTimeInterval: any // 打开画布线稿id sketchId: 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) options.generateManager && (this.generateManager = options.generateManager) } 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.mxHistory = ref(50) this.historyList = ref([]) this.historyIndex = ref(0) this.sketchId = ref(options.sketchId) this.saveCanvasTimeInterval = 6000 this.saveCanvasTime = null this.activeNodeID = ref("") this.nodes = ref([]); this.nodes_ = computed(() => { return this.nodes.value.map((node, index) => { 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) if (!isSuperior && isSubord) {// 没有上级 有下级 obj.type = NODE_TYPE.INPUT; } else if (isSuperior && isSubord) {// 有上级 有下级 obj.type = NODE_TYPE.SECONDARY; } else if (isSuperior && !isSubord) {// 有上级 没有下级 obj.type = NODE_TYPE.OUTPUT; } else {// 其他情况-没有上级 没有下级 obj.type = NODE_TYPE.ALONE; } return obj }) }) this.edges = computed(() => { const arr = [] this.nodes.value.forEach((node, index) => { const superiorID = node.data.superiorID; const isSuperior = this.nodes.value.some((v) => v.id === superiorID) if (isSuperior) { const source = node.data.superiorID const target = node.id arr.push({ id: `el-${source}-${target}`, source: source, target: target, selectable: false, visible: (node.data.type == NODE_DATATYPE.RESULT_IMAGE && node.data.isActive) || node.data.type !== NODE_DATATYPE.RESULT_IMAGE, type: 'default' }) } }) return arr }) } /** 设置激活节点 */ setActiveNodeID(id: string) { this.activeNodeID.value = id;this.showNodeConnections(id) } /** 添加节点 */ addNode(node: NodesItem) { this.nodes.value.push(node); this.recordState() this.exportFlow() if(chatAssistant[node.data.type])myEvent.emit('assistantPushChat',chatAssistant[node.data.type]) } /** 删除节点 */ async deleteNode(id: string) { this.nodes.value = this.nodes.value.filter((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] } /** 获取上级生成节点的图片 */ getSuperiorNodeImage(superiorID: string) { const superiorNode = this.getNodeById(superiorID) if(!superiorNode){ // ElMessage.error(t('FlowCanvas.cannotFindSuperiorImage')) return null } const superiorNodeUrl = superiorNode.data.data.imageProcessTasks.filter((item)=>{ return item.taskId == superiorNode.data.data.selectTaskId })[0]?.url return superiorNodeUrl } /** 获取下级所有子级节点 */ async deleteSubordinateAllNodes(id: string,{ isElMessageBox } = { isElMessageBox: false }) { const node = this.getNodeById(id) if (!node) return console.warn(`没有找到指定id:${id}`) if (node.data.disableDelete) return ElMessage.error(t('FlowCanvas.initialNodeProhibited')) const result = [node] const findChildren = (parentId: string) => { const children = this.nodes.value.filter(item => item.data.superiorID === parentId) children.forEach(child => { if(child.data.type !== NODE_DATATYPE.RESULT_IMAGE){ result.push(child) } findChildren(child.id) }) } findChildren(id) let deletePromise: any = true if (isElMessageBox) { deletePromise = await new Promise((resolve, reject) => { ElMessageBox.confirm( result.length > 1 ? t('FlowCanvas.deleteSubordinateCard') : t('FlowCanvas.deleteCardConfirm'), '', { confirmButtonText: t('FlowCanvas.confirm'), cancelButtonText: t('FlowCanvas.cancel'), } ).then(() => {resolve(true) }).catch(() => { resolve(false) }) }) } if(!deletePromise) return console.log('删除操作被取消') if(node.data.data?.imageProcessTasks?.length > 1){ node.data.data.imageProcessTasks = node.data.data.imageProcessTasks.filter((item) => item.taskId !== node.data.data.selectTaskId) return } this.deleteNode(id) result.forEach(item => { this.deleteNode(item.id) }) this.recordState() this.exportFlow() } /** 设置工具 */ 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 } /** 获取所有下级节点 */ getSubordNodes(id: string) { return this.nodes.value.filter((node: NodesItem) => node.data.superiorID === id) } /** 设置节点层级至最顶部 */ 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)) } /** 设置节点层级至最低部 */ 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)) } /** 记录状态 */ recordState() { if (this.historyIndex.value < this.historyList.value.length - 1) { this.historyList.value.splice(this.historyIndex.value + 1) } 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 } /** 画布数据存储 */ async exportFlow (time:number = 0){ if(!this.sketchId.value)return clearTimeout(this.saveCanvasTime) await new Promise((resolve) => { this.saveCanvasTime = setTimeout(()=>{ putSketchFlowCanvas({ id: this.sketchId.value, canvasData: JSON.stringify(this.nodes.value) }).then(() => { resolve(true) }).catch(() => { resolve(true) }) },time) }) } /** 撤回状态 */ undoState() { const 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) } /** 重做状态 */ redoState() { const 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) } /** 显示指定子节点和父节点连接线,隐藏父节点和其他子节点链接线, */ showNodeConnections(id: string) { if(!id) return const node = this.getNodeById(id) if(!node?.data?.superiorID) return 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 } }) } dispose() { clearTimeout(this.saveCanvasTime) this.historyList.value = [] this.historyIndex.value = 0 } }