fix: Loop validation and other bugs (#4082)
parent
3fad820e99
commit
4266a74b8c
|
|
@ -75,6 +75,7 @@ export default {
|
||||||
nodeUnavailable: 'Node unavailable',
|
nodeUnavailable: 'Node unavailable',
|
||||||
needConnect1: 'The branch of the node needs to be connected',
|
needConnect1: 'The branch of the node needs to be connected',
|
||||||
cannotEndNode: 'This node cannot be used as an end node',
|
cannotEndNode: 'This node cannot be used as an end node',
|
||||||
|
loopNodeBreakNodeRequired: 'Wireless loop must have a Break node',
|
||||||
},
|
},
|
||||||
nodes: {
|
nodes: {
|
||||||
classify: {
|
classify: {
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ export default {
|
||||||
needConnect1: '节点的',
|
needConnect1: '节点的',
|
||||||
needConnect2: '分支需要连接',
|
needConnect2: '分支需要连接',
|
||||||
cannotEndNode: '节点不能当做结束节点',
|
cannotEndNode: '节点不能当做结束节点',
|
||||||
|
loopNodeBreakNodeRequired: '无线循环 必须存在 Break 节点',
|
||||||
},
|
},
|
||||||
nodes: {
|
nodes: {
|
||||||
classify: {
|
classify: {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ export default {
|
||||||
needConnect1: '節點的',
|
needConnect1: '節點的',
|
||||||
needConnect2: '分支需要連接',
|
needConnect2: '分支需要連接',
|
||||||
cannotEndNode: '節點不能當做結束節點',
|
cannotEndNode: '節點不能當做結束節點',
|
||||||
|
loopNodeBreakNodeRequired: '無線迴圈必須存在Break節點',
|
||||||
},
|
},
|
||||||
nodes: {
|
nodes: {
|
||||||
classify: {
|
classify: {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ const end_nodes: Array<string> = [
|
||||||
WorkflowType.TextToVideoGenerateNode,
|
WorkflowType.TextToVideoGenerateNode,
|
||||||
WorkflowType.ImageGenerateNode,
|
WorkflowType.ImageGenerateNode,
|
||||||
WorkflowType.LoopBodyNode,
|
WorkflowType.LoopBodyNode,
|
||||||
|
WorkflowType.LoopNode,
|
||||||
|
WorkflowType.LoopBreakNode,
|
||||||
]
|
]
|
||||||
export class WorkFlowInstance {
|
export class WorkFlowInstance {
|
||||||
nodes
|
nodes
|
||||||
|
|
@ -29,7 +31,9 @@ export class WorkFlowInstance {
|
||||||
* 校验开始节点
|
* 校验开始节点
|
||||||
*/
|
*/
|
||||||
private is_valid_start_node() {
|
private is_valid_start_node() {
|
||||||
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Start)
|
const start_node_list = this.nodes.filter((item) =>
|
||||||
|
[WorkflowType.Start, WorkflowType.LoopStartNode].includes(item.id),
|
||||||
|
)
|
||||||
if (start_node_list.length == 0) {
|
if (start_node_list.length == 0) {
|
||||||
throw t('views.applicationWorkflow.validate.startNodeRequired')
|
throw t('views.applicationWorkflow.validate.startNodeRequired')
|
||||||
} else if (start_node_list.length > 1) {
|
} else if (start_node_list.length > 1) {
|
||||||
|
|
@ -57,12 +61,20 @@ export class WorkFlowInstance {
|
||||||
this.is_valid_nodes()
|
this.is_valid_nodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_loop_valid() {
|
||||||
|
this.is_valid_start_node()
|
||||||
|
this.is_valid_work_flow()
|
||||||
|
this.is_valid_nodes()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取开始节点
|
* 获取开始节点
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
get_start_node() {
|
get_start_node() {
|
||||||
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Start)
|
const start_node_list = this.nodes.filter((item) =>
|
||||||
|
[WorkflowType.Start, WorkflowType.LoopStartNode].includes(item.id),
|
||||||
|
)
|
||||||
return start_node_list[0]
|
return start_node_list[0]
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,7 +85,9 @@ export class WorkFlowInstance {
|
||||||
const base_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base)
|
const base_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base)
|
||||||
return base_node_list[0]
|
return base_node_list[0]
|
||||||
}
|
}
|
||||||
|
extis_break_node() {
|
||||||
|
return this.nodes.some((item) => item.id === WorkflowType.LoopBreakNode)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 校验工作流
|
* 校验工作流
|
||||||
* @param up_node 上一个节点
|
* @param up_node 上一个节点
|
||||||
|
|
@ -117,7 +131,11 @@ export class WorkFlowInstance {
|
||||||
}
|
}
|
||||||
private is_valid_nodes() {
|
private is_valid_nodes() {
|
||||||
for (const node of this.nodes) {
|
for (const node of this.nodes) {
|
||||||
if (node.type !== WorkflowType.Base && node.type !== WorkflowType.Start) {
|
if (
|
||||||
|
node.type !== WorkflowType.Base &&
|
||||||
|
node.type !== WorkflowType.Start &&
|
||||||
|
node.type !== WorkflowType.LoopStartNode
|
||||||
|
) {
|
||||||
if (!this.edges.some((edge) => edge.targetNodeId === node.id)) {
|
if (!this.edges.some((edge) => edge.targetNodeId === node.id)) {
|
||||||
throw `${t('views.applicationWorkflow.validate.notInWorkFlowNode')}:${node.properties.stepName}`
|
throw `${t('views.applicationWorkflow.validate.notInWorkFlowNode')}:${node.properties.stepName}`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,51 @@ import Dagre from '@/workflow/plugins/dagre'
|
||||||
import { initDefaultShortcut } from '@/workflow/common/shortcut'
|
import { initDefaultShortcut } from '@/workflow/common/shortcut'
|
||||||
import LoopBodyContainer from '@/workflow/nodes/loop-body-node/LoopBodyContainer.vue'
|
import LoopBodyContainer from '@/workflow/nodes/loop-body-node/LoopBodyContainer.vue'
|
||||||
import { WorkflowMode } from '@/enums/application'
|
import { WorkflowMode } from '@/enums/application'
|
||||||
|
import { WorkFlowInstance } from '@/workflow/common/validate'
|
||||||
|
import { t } from '@/locales'
|
||||||
const nodes: any = import.meta.glob('@/workflow/nodes/**/index.ts', { eager: true })
|
const nodes: any = import.meta.glob('@/workflow/nodes/**/index.ts', { eager: true })
|
||||||
const props = defineProps<{ nodeModel: any }>()
|
const props = defineProps<{ nodeModel: any }>()
|
||||||
const containerRef = ref()
|
const containerRef = ref()
|
||||||
|
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
|
const workflow = new WorkFlowInstance(lf.value.getGraphData())
|
||||||
return Promise.all(lf.value.graphModel.nodes.map((element: any) => element?.validate?.()))
|
return Promise.all(lf.value.graphModel.nodes.map((element: any) => element?.validate?.()))
|
||||||
|
.then(() => {
|
||||||
|
const loop_node_id = props.nodeModel.properties.loop_node_id
|
||||||
|
const loop_node = props.nodeModel.graphModel.getNodeModelById(loop_node_id)
|
||||||
|
try {
|
||||||
|
workflow.is_loop_valid()
|
||||||
|
if (loop_node.properties.node_data.loop_type == 'LOOP' && !workflow.extis_break_node()) {
|
||||||
|
return Promise.reject({
|
||||||
|
node: loop_node,
|
||||||
|
errMessage: t('views.applicationWorkflow.validate.loopNodeBreakNodeRequired'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({})
|
||||||
|
} catch (e) {
|
||||||
|
return Promise.reject({ node: loop_node, errMessage: e })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
props.nodeModel.graphModel.selectNodeById(props.nodeModel.id)
|
||||||
|
props.nodeModel.graphModel.transformModel.focusOn(
|
||||||
|
props.nodeModel.x,
|
||||||
|
props.nodeModel.y,
|
||||||
|
props.nodeModel.width,
|
||||||
|
props.nodeModel.height,
|
||||||
|
)
|
||||||
|
throw e
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const set_loop_body = () => {
|
const set_loop_body = () => {
|
||||||
const loop_node_id = props.nodeModel.properties.loop_node_id
|
const loop_node_id = props.nodeModel.properties.loop_node_id
|
||||||
const loop_node = props.nodeModel.graphModel.getNodeModelById(loop_node_id)
|
const loop_node = props.nodeModel.graphModel.getNodeModelById(loop_node_id)
|
||||||
loop_node.properties.node_data.loop_body = lf.value.getGraphData()
|
loop_node.properties.node_data.loop_body = lf.value.getGraphData()
|
||||||
|
loop_node.properties.node_data.loop = {
|
||||||
|
x: props.nodeModel.x,
|
||||||
|
y: props.nodeModel.y,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const refresh_loop_fields = (fields: Array<any>) => {
|
const refresh_loop_fields = (fields: Array<any>) => {
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,15 @@ onMounted(() => {
|
||||||
const nodeOutgoingNode = props.nodeModel.graphModel.getNodeOutgoingNode(props.nodeModel.id)
|
const nodeOutgoingNode = props.nodeModel.graphModel.getNodeOutgoingNode(props.nodeModel.id)
|
||||||
if (!nodeOutgoingNode.some((item: any) => item.type == loopBodyNode.type)) {
|
if (!nodeOutgoingNode.some((item: any) => item.type == loopBodyNode.type)) {
|
||||||
let workflow = { nodes: [loopStartNode], edges: [] }
|
let workflow = { nodes: [loopStartNode], edges: [] }
|
||||||
|
let x = props.nodeModel.x
|
||||||
|
let y = props.nodeModel.y + 200
|
||||||
if (props.nodeModel.properties.node_data.loop_body) {
|
if (props.nodeModel.properties.node_data.loop_body) {
|
||||||
workflow = props.nodeModel.properties.node_data.loop_body
|
workflow = props.nodeModel.properties.node_data.loop_body
|
||||||
}
|
}
|
||||||
|
if (props.nodeModel.properties.node_data.loop) {
|
||||||
|
x = props.nodeModel.properties.node_data.loop.x
|
||||||
|
y = props.nodeModel.properties.node_data.loop.y
|
||||||
|
}
|
||||||
const nodeModel = props.nodeModel.graphModel.addNode({
|
const nodeModel = props.nodeModel.graphModel.addNode({
|
||||||
type: loopBodyNode.type,
|
type: loopBodyNode.type,
|
||||||
properties: {
|
properties: {
|
||||||
|
|
@ -130,8 +136,8 @@ onMounted(() => {
|
||||||
workflow: workflow,
|
workflow: workflow,
|
||||||
loop_node_id: props.nodeModel.id,
|
loop_node_id: props.nodeModel.id,
|
||||||
},
|
},
|
||||||
x: props.nodeModel.x,
|
x: x,
|
||||||
y: props.nodeModel.y + loopBodyNode.height,
|
y: y,
|
||||||
})
|
})
|
||||||
props.nodeModel.graphModel.addEdge({
|
props.nodeModel.graphModel.addEdge({
|
||||||
type: 'loop-edge',
|
type: 'loop-edge',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue