Browse Source

Merge pull request #3500 from break60/1.3.2-release

[Fix-3469][ui]The value of maintenance resources and the filtering of…
pull/3/MERGE
xingchun-chen 4 years ago committed by GitHub
parent
commit
c0bed396c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
  2. 37
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/flink.vue
  3. 38
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/mr.vue
  4. 9
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/python.vue
  5. 9
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/shell.vue
  6. 35
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/spark.vue
  7. 20
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js
  8. 1
      dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue
  9. 3
      dolphinscheduler-ui/src/js/conf/home/pages/dag/index.vue
  10. 1
      dolphinscheduler-ui/src/js/conf/home/pages/dag/instanceDetails.vue
  11. 11
      dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js
  12. 1
      dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js
  13. 2
      dolphinscheduler-ui/src/js/conf/home/store/dag/state.js
  14. 6
      dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
  15. 6
      dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

1
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue

@ -434,7 +434,6 @@
this.$message.warning(`${i18n.$t('Failed to create node to save')}`) this.$message.warning(`${i18n.$t('Failed to create node to save')}`)
return return
} }
// Global parameters (optional) // Global parameters (optional)
this._udpTopFloorPop().then(() => { this._udpTopFloorPop().then(() => {
return this._save() return this._save()

37
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/flink.vue

@ -22,6 +22,7 @@
<x-select <x-select
style="width: 130px;" style="width: 130px;"
v-model="programType" v-model="programType"
@on-change="_onChange"
:disabled="isDetails"> :disabled="isDetails">
<x-option <x-option
v-for="city in programTypeList" v-for="city in programTypeList"
@ -181,6 +182,8 @@
// Master jar package(List) // Master jar package(List)
mainJarLists: [], mainJarLists: [],
mainJarList: [], mainJarList: [],
jarList: [],
pyList: [],
// Deployment method // Deployment method
deployMode: 'cluster', deployMode: 'cluster',
// Resource(list) // Resource(list)
@ -221,6 +224,16 @@
}, },
mixins: [disabledState], mixins: [disabledState],
methods: { methods: {
/**
* programType change
*/
_onChange(o) {
if(o.value === 'PYTHON') {
this.mainJarLists = this.pyList
} else {
this.mainJarLists = this.jarList
}
},
/** /**
* getResourceId * getResourceId
*/ */
@ -304,7 +317,7 @@
// noRes // noRes
if (this.noRes.length>0) { if (this.noRes.length>0) {
this.$message.warning(`${i18n.$t('Please delete all non-existent resources')}`) this.$message.warning(`${i18n.$t('Please delete all non-existing resources')}`)
return false return false
} }
@ -389,19 +402,20 @@
} }
let noResources = [{ let noResources = [{
id: -1, id: -1,
name: $t('Unauthorized or deleted resources'), name: $t('No resources exist'),
fullName: '/'+$t('Unauthorized or deleted resources'), fullName: '/'+$t('No resources exist'),
children: [] children: []
}] }]
if(optionsCmp.length>0) { if(optionsCmp.length>0) {
this.allNoResources = optionsCmp this.allNoResources = optionsCmp
optionsCmp = optionsCmp.map(item=>{ optionsCmp = optionsCmp.map(item=>{
return {id: item.id,name: item.name,fullName: item.res} return {id: item.id,name: item.name || item.res,fullName: item.res}
}) })
optionsCmp.forEach(item=>{ optionsCmp.forEach(item=>{
item.isNew = true item.isNew = true
}) })
noResources[0].children = optionsCmp noResources[0].children = optionsCmp
this.mainJarList = _.filter(this.mainJarList, o=> { return o.id!==-1 })
this.mainJarList = this.mainJarList.concat(noResources) this.mainJarList = this.mainJarList.concat(noResources)
} }
} }
@ -465,13 +479,24 @@
} }
}, },
created () { created () {
let o = this.backfillItem
let item = this.store.state.dag.resourcesListS let item = this.store.state.dag.resourcesListS
let items = this.store.state.dag.resourcesListJar let items = this.store.state.dag.resourcesListJar
let pythonList = this.store.state.dag.resourcesListPy
this.diGuiTree(item) this.diGuiTree(item)
this.diGuiTree(items) this.diGuiTree(items)
this.diGuiTree(pythonList)
this.mainJarList = item this.mainJarList = item
this.mainJarLists = items this.jarList = items
let o = this.backfillItem this.pyList = pythonList
if(!_.isEmpty(o) && o.params.programType === 'PYTHON') {
this.mainJarLists = pythonList
} else {
this.mainJarLists = items
}
// Non-null objects represent backfill // Non-null objects represent backfill
if (!_.isEmpty(o)) { if (!_.isEmpty(o)) {
this.mainClass = o.params.mainClass || '' this.mainClass = o.params.mainClass || ''

38
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/mr.vue

@ -19,7 +19,7 @@
<m-list-box> <m-list-box>
<div slot="text">{{$t('Program Type')}}</div> <div slot="text">{{$t('Program Type')}}</div>
<div slot="content"> <div slot="content">
<x-select v-model="programType" :disabled="isDetails" style="width: 110px;"> <x-select v-model="programType" @on-change="_onChange" :disabled="isDetails" style="width: 110px;">
<x-option <x-option
v-for="city in programTypeList" v-for="city in programTypeList"
:key="city.code" :key="city.code"
@ -117,6 +117,8 @@
// Main jar package (List) // Main jar package (List)
mainJarLists: [], mainJarLists: [],
mainJarList: [], mainJarList: [],
jarList: [],
pyList: [],
// Resource(list) // Resource(list)
resourceList: [], resourceList: [],
// Cache ResourceList // Cache ResourceList
@ -145,6 +147,16 @@
}, },
mixins: [disabledState], mixins: [disabledState],
methods: { methods: {
/**
* programType change
*/
_onChange(o) {
if(o.value === 'PYTHON') {
this.mainJarLists = this.pyList
} else {
this.mainJarLists = this.jarList
}
},
/** /**
* getResourceId * getResourceId
*/ */
@ -230,19 +242,20 @@
} }
let noResources = [{ let noResources = [{
id: -1, id: -1,
name: $t('Unauthorized or deleted resources'), name: $t('No resources exist'),
fullName: '/'+$t('Unauthorized or deleted resources'), fullName: '/'+$t('No resources exist'),
children: [] children: []
}] }]
if(optionsCmp.length>0) { if(optionsCmp.length>0) {
this.allNoResources = optionsCmp this.allNoResources = optionsCmp
optionsCmp = optionsCmp.map(item=>{ optionsCmp = optionsCmp.map(item=>{
return {id: item.id,name: item.name,fullName: item.res} return {id: item.id,name: item.name || item.res,fullName: item.res}
}) })
optionsCmp.forEach(item=>{ optionsCmp.forEach(item=>{
item.isNew = true item.isNew = true
}) })
noResources[0].children = optionsCmp noResources[0].children = optionsCmp
this.mainJarList = _.filter(this.mainJarList, o=> { return o.id!==-1 })
this.mainJarList = this.mainJarList.concat(noResources) this.mainJarList = this.mainJarList.concat(noResources)
} }
} }
@ -263,7 +276,7 @@
// noRes // noRes
if (this.noRes.length>0) { if (this.noRes.length>0) {
this.$message.warning(`${i18n.$t('Please delete all non-existent resources')}`) this.$message.warning(`${i18n.$t('Please delete all non-existing resources')}`)
return false return false
} }
@ -343,13 +356,24 @@
} }
}, },
created () { created () {
let o = this.backfillItem
let item = this.store.state.dag.resourcesListS let item = this.store.state.dag.resourcesListS
let items = this.store.state.dag.resourcesListJar let items = this.store.state.dag.resourcesListJar
let pythonList = this.store.state.dag.resourcesListPy
this.diGuiTree(item) this.diGuiTree(item)
this.diGuiTree(items) this.diGuiTree(items)
this.diGuiTree(pythonList)
this.mainJarList = item this.mainJarList = item
this.mainJarLists = items this.jarList = items
let o = this.backfillItem this.pyList = pythonList
if(!_.isEmpty(o) && o.params.programType === 'PYTHON') {
this.mainJarLists = pythonList
} else {
this.mainJarLists = items
}
// Non-null objects represent backfill // Non-null objects represent backfill
if (!_.isEmpty(o)) { if (!_.isEmpty(o)) {

9
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/python.vue

@ -129,7 +129,7 @@
// noRes // noRes
if (this.noRes.length>0) { if (this.noRes.length>0) {
this.$message.warning(`${i18n.$t('Please delete all non-existent resources')}`) this.$message.warning(`${i18n.$t('Please delete all non-existing resources')}`)
return false return false
} }
@ -222,19 +222,20 @@
} }
let noResources = [{ let noResources = [{
id: -1, id: -1,
name: $t('Unauthorized or deleted resources'), name: $t('No resources exist'),
fullName: '/'+$t('Unauthorized or deleted resources'), fullName: '/'+$t('No resources exist'),
children: [] children: []
}] }]
if(optionsCmp.length>0) { if(optionsCmp.length>0) {
this.allNoResources = optionsCmp this.allNoResources = optionsCmp
optionsCmp = optionsCmp.map(item=>{ optionsCmp = optionsCmp.map(item=>{
return {id: item.id,name: item.name,fullName: item.res} return {id: item.id,name: item.name || item.res,fullName: item.res}
}) })
optionsCmp.forEach(item=>{ optionsCmp.forEach(item=>{
item.isNew = true item.isNew = true
}) })
noResources[0].children = optionsCmp noResources[0].children = optionsCmp
this.resourceOptions = _.filter(this.resourceOptions, o=> { return o.id!==-1 })
this.resourceOptions = this.resourceOptions.concat(noResources) this.resourceOptions = this.resourceOptions.concat(noResources)
} }
} }

9
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/shell.vue

@ -165,7 +165,7 @@
} }
// noRes // noRes
if (this.noRes.length>0) { if (this.noRes.length>0) {
this.$message.warning(`${i18n.$t('Please delete all non-existent resources')}`) this.$message.warning(`${i18n.$t('Please delete all non-existing resources')}`)
return false return false
} }
// Process resourcelist // Process resourcelist
@ -260,19 +260,20 @@
} }
let noResources = [{ let noResources = [{
id: -1, id: -1,
name: $t('Unauthorized or deleted resources'), name: $t('No resources exist'),
fullName: '/'+$t('Unauthorized or deleted resources'), fullName: '/'+$t('No resources exist'),
children: [] children: []
}] }]
if(optionsCmp.length>0) { if(optionsCmp.length>0) {
this.allNoResources = optionsCmp this.allNoResources = optionsCmp
optionsCmp = optionsCmp.map(item=>{ optionsCmp = optionsCmp.map(item=>{
return {id: item.id,name: item.name,fullName: item.res} return {id: item.id,name: item.name || item.res,fullName: item.res}
}) })
optionsCmp.forEach(item=>{ optionsCmp.forEach(item=>{
item.isNew = true item.isNew = true
}) })
noResources[0].children = optionsCmp noResources[0].children = optionsCmp
this.options = _.filter(this.options, o=> { return o.id!==-1 })
this.options = this.options.concat(noResources) this.options = this.options.concat(noResources)
} }
} }

35
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/spark.vue

@ -22,6 +22,7 @@
<x-select <x-select
style="width: 130px;" style="width: 130px;"
v-model="programType" v-model="programType"
@on-change="_onChange"
:disabled="isDetails"> :disabled="isDetails">
<x-option <x-option
v-for="city in programTypeList" v-for="city in programTypeList"
@ -220,6 +221,8 @@
// Master jar package(List) // Master jar package(List)
mainJarLists: [], mainJarLists: [],
mainJarList: [], mainJarList: [],
jarList: [],
pyList: [],
// Deployment method // Deployment method
deployMode: 'cluster', deployMode: 'cluster',
// Resource(list) // Resource(list)
@ -264,6 +267,16 @@
}, },
mixins: [disabledState], mixins: [disabledState],
methods: { methods: {
/**
* programType change
*/
_onChange(o) {
if(o.value === 'PYTHON') {
this.mainJarLists = this.pyList
} else {
this.mainJarLists = this.jarList
}
},
/** /**
* getResourceId * getResourceId
*/ */
@ -349,19 +362,20 @@
} }
let noResources = [{ let noResources = [{
id: -1, id: -1,
name: $t('Unauthorized or deleted resources'), name: $t('No resources exist'),
fullName: '/'+$t('Unauthorized or deleted resources'), fullName: '/'+$t('No resources exist'),
children: [] children: []
}] }]
if(optionsCmp.length>0) { if(optionsCmp.length>0) {
this.allNoResources = optionsCmp this.allNoResources = optionsCmp
optionsCmp = optionsCmp.map(item=>{ optionsCmp = optionsCmp.map(item=>{
return {id: item.id,name: item.name,fullName: item.res} return {id: item.id,name: item.name || item.res,fullName: item.res}
}) })
optionsCmp.forEach(item=>{ optionsCmp.forEach(item=>{
item.isNew = true item.isNew = true
}) })
noResources[0].children = optionsCmp noResources[0].children = optionsCmp
this.mainJarList = _.filter(this.mainJarList, o=> { return o.id!==-1 })
this.mainJarList = this.mainJarList.concat(noResources) this.mainJarList = this.mainJarList.concat(noResources)
} }
} }
@ -387,7 +401,7 @@
// noRes // noRes
if (this.noRes.length>0) { if (this.noRes.length>0) {
this.$message.warning(`${i18n.$t('Please delete all non-existent resources')}`) this.$message.warning(`${i18n.$t('Please delete all non-existing resources')}`)
return false return false
} }
@ -512,13 +526,22 @@
} }
}, },
created () { created () {
let o = this.backfillItem
let item = this.store.state.dag.resourcesListS let item = this.store.state.dag.resourcesListS
let items = this.store.state.dag.resourcesListJar let items = this.store.state.dag.resourcesListJar
let pythonList = this.store.state.dag.resourcesListPy
this.diGuiTree(item) this.diGuiTree(item)
this.diGuiTree(items) this.diGuiTree(items)
this.diGuiTree(pythonList)
this.mainJarList = item this.mainJarList = item
this.mainJarLists = items this.jarList = items
let o = this.backfillItem this.pyList = pythonList
if(!_.isEmpty(o) && o.params.programType === 'PYTHON') {
this.mainJarLists = pythonList
} else {
this.mainJarLists = items
}
// Non-null objects represent backfill // Non-null objects represent backfill
if (!_.isEmpty(o)) { if (!_.isEmpty(o)) {

20
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js

@ -666,7 +666,18 @@ JSP.prototype.saveStore = function () {
y: v.y y: v.y
} }
}) })
let targetArrBool = false
_.forEach(locations, item => {
if(item.targetarr) {
targetArrBool = true
return false
}
})
if(connects.length && !targetArrBool) {
Vue.$message.warning(`${i18n.$t('The workflow canvas is abnormal and cannot be saved, please recreate')}`)
return false
}
// return false
// Storage node // Storage node
store.commit('dag/setTasks', tasks) store.commit('dag/setTasks', tasks)
// Store coordinate information // Store coordinate information
@ -697,13 +708,6 @@ JSP.prototype.handleEvent = function () {
console.log(sourceId,targetId) console.log(sourceId,targetId)
let rtTargetArrs = rtTargetArr(targetId) let rtTargetArrs = rtTargetArr(targetId)
let rtSouceArrs = rtTargetArr(sourceId) let rtSouceArrs = rtTargetArr(sourceId)
/**
* When connecting, connection is prohibited when the sourceId and target nodes are empty
*/
if(!sourceId && !targetId) {
Vue.$message.warning(`${i18n.$t('This canvas is abnormal and the node connection cannot be made. Please save or exit the current workflow')}`)
return false
}
/** /**
* Recursive search for nodes * Recursive search for nodes
*/ */

1
dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue

@ -62,6 +62,7 @@
this.getResourcesList(), this.getResourcesList(),
// get jar // get jar
this.getResourcesListJar(), this.getResourcesListJar(),
this.getResourcesListJar('PYTHON'),
// get worker group list // get worker group list
this.getWorkerGroupsAll(), this.getWorkerGroupsAll(),
this.getTenantList() this.getTenantList()

3
dolphinscheduler-ui/src/js/conf/home/pages/dag/index.vue

@ -57,10 +57,9 @@
this.getProjectList(), this.getProjectList(),
// get jar // get jar
this.getResourcesListJar(), this.getResourcesListJar(),
this.getResourcesListJar('PYTHON'),
// get resource // get resource
this.getResourcesList(), this.getResourcesList(),
// get jar
this.getResourcesListJar(),
// get worker group list // get worker group list
this.getWorkerGroupsAll(), this.getWorkerGroupsAll(),
this.getTenantList() this.getTenantList()

1
dolphinscheduler-ui/src/js/conf/home/pages/dag/instanceDetails.vue

@ -64,6 +64,7 @@
this.getResourcesList(), this.getResourcesList(),
// get jar // get jar
this.getResourcesListJar(), this.getResourcesListJar(),
this.getResourcesListJar('PYTHON'),
// get worker group list // get worker group list
this.getWorkerGroupsAll(), this.getWorkerGroupsAll(),
this.getTenantList() this.getTenantList()

11
dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js

@ -374,16 +374,21 @@ export default {
/** /**
* get jar * get jar
*/ */
getResourcesListJar ({ state }) { getResourcesListJar ({ state }, payload) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (state.resourcesListJar.length) { if (state.resourcesListJar.length) {
resolve() resolve()
return return
} }
io.get('resources/list/jar', { io.get('resources/list/jar', {
type: 'FILE' type: 'FILE',
programType: payload
}, res => { }, res => {
state.resourcesListJar = res.data if(payload) {
state.resourcesListPy = res.data
} else {
state.resourcesListJar = res.data
}
resolve(res.data) resolve(res.data)
}).catch(res => { }).catch(res => {
reject(res) reject(res)

1
dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js

@ -109,6 +109,7 @@ export default {
state.processListS = (payload && payload.processListS) || [] state.processListS = (payload && payload.processListS) || []
state.resourcesListS = (payload && payload.resourcesListS) || [] state.resourcesListS = (payload && payload.resourcesListS) || []
state.resourcesListJar = (payload && payload.resourcesListJar) || [] state.resourcesListJar = (payload && payload.resourcesListJar) || []
state.resourcesListPy = (payload && payload.resourcesListPy) || []
state.projectListS = (payload && payload.projectListS) || [] state.projectListS = (payload && payload.projectListS) || []
state.isDetails = (payload && payload.isDetails) || false state.isDetails = (payload && payload.isDetails) || false
state.runFlag = (payload && payload.runFlag) || '' state.runFlag = (payload && payload.runFlag) || ''

2
dolphinscheduler-ui/src/js/conf/home/store/dag/state.js

@ -55,6 +55,8 @@ export default {
resourcesListS: [], resourcesListS: [],
// tasks resourcesListJar // tasks resourcesListJar
resourcesListJar: [], resourcesListJar: [],
// tasks resourcesListPy
resourcesListPy: [],
// tasks datasource Type // tasks datasource Type
dsTypeListS: [ dsTypeListS: [
{ {

6
dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js

@ -591,8 +591,8 @@ export default {
'Branch flow': 'Branch flow', 'Branch flow': 'Branch flow',
'Cannot select the same node for successful branch flow and failed branch flow': 'Cannot select the same node for successful branch flow and failed branch flow', 'Cannot select the same node for successful branch flow and failed branch flow': 'Cannot select the same node for successful branch flow and failed branch flow',
'Successful branch flow and failed branch flow are required': 'conditions node Successful and failed branch flow are required', 'Successful branch flow and failed branch flow are required': 'conditions node Successful and failed branch flow are required',
'Unauthorized or deleted resources': 'Unauthorized or deleted resources', 'No resources exist': 'No resources exist',
'Please delete all non-existent resources': 'Please delete all non-existent resources', 'Please delete all non-existing resources': 'Please delete all non-existing resources',
'The Worker group no longer exists, please select the correct Worker group!': 'The Worker group no longer exists, please select the correct Worker group!', 'The Worker group no longer exists, please select the correct Worker group!': 'The Worker group no longer exists, please select the correct Worker group!',
'Please confirm whether the workflow has been saved before downloading': 'Please confirm whether the workflow has been saved before downloading', 'Please confirm whether the workflow has been saved before downloading': 'Please confirm whether the workflow has been saved before downloading',
'User name length is between 3 and 39': 'User name length is between 3 and 39', 'User name length is between 3 and 39': 'User name length is between 3 and 39',
@ -601,5 +601,5 @@ export default {
'Connection name': 'Connection name', 'Connection name': 'Connection name',
'Current connection settings': 'Current connection settings', 'Current connection settings': 'Current connection settings',
'Please save the DAG before formatting': 'Please save the DAG before formatting', 'Please save the DAG before formatting': 'Please save the DAG before formatting',
'This canvas is abnormal and the node connection cannot be made. Please save or exit the current workflow': 'This canvas is abnormal and the node connection cannot be made. Please save or exit the current workflow' 'The workflow canvas is abnormal and cannot be saved, please recreate': 'The workflow canvas is abnormal and cannot be saved, please recreate'
} }

6
dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

@ -591,8 +591,8 @@ export default {
'Branch flow': '分支流转', 'Branch flow': '分支流转',
'Cannot select the same node for successful branch flow and failed branch flow': '成功分支流转和失败分支流转不能选择同一个节点', 'Cannot select the same node for successful branch flow and failed branch flow': '成功分支流转和失败分支流转不能选择同一个节点',
'Successful branch flow and failed branch flow are required': 'conditions节点成功和失败分支流转必填', 'Successful branch flow and failed branch flow are required': 'conditions节点成功和失败分支流转必填',
'Unauthorized or deleted resources': '未授权或已删除资源', 'No resources exist': '不存在资源',
'Please delete all non-existent resources': '请删除所有未授权或已删除资源', 'Please delete all non-existing resources': '请删除所有不存在资源',
'The Worker group no longer exists, please select the correct Worker group!': '该Worker分组已经不存在请选择正确的Worker分组', 'The Worker group no longer exists, please select the correct Worker group!': '该Worker分组已经不存在请选择正确的Worker分组',
'Please confirm whether the workflow has been saved before downloading': '下载前请确定工作流是否已保存', 'Please confirm whether the workflow has been saved before downloading': '下载前请确定工作流是否已保存',
'User name length is between 3 and 39': '用户名长度在339之间', 'User name length is between 3 and 39': '用户名长度在339之间',
@ -607,5 +607,5 @@ export default {
'Connection name': '连线名', 'Connection name': '连线名',
'Current connection settings': '当前连线设置', 'Current connection settings': '当前连线设置',
'Please save the DAG before formatting': '格式化前请先保存DAG', 'Please save the DAG before formatting': '格式化前请先保存DAG',
'This canvas is abnormal and the node connection cannot be made. Please save or exit the current workflow': '此画布异常无法进行节点连线请保存或退出当前工作流' 'The workflow canvas is abnormal and cannot be saved, please recreate': '该工作流画布异常无法保存请重新创建'
} }

Loading…
Cancel
Save