diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts index fde10bd784..e0feaa5ec1 100644 --- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts +++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts @@ -559,7 +559,12 @@ const project = { value: 'Value', success: 'Success', delete_cell: 'Delete selected edges and nodes', - online_directly: 'Whether to go online the process definition' + online_directly: 'Whether to go online the process definition', + dag_name_empty: 'DAG graph name cannot be empty', + positive_integer: 'Please enter a positive integer greater than 0', + prop_empty: 'prop is empty', + prop_repeat: 'prop is repeat', + node_not_created: 'Failed to save node not created' }, node: { current_node_settings: 'Current node settings', diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts index 4ad6a96c39..d11fedaf90 100644 --- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts +++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts @@ -557,7 +557,12 @@ const project = { value: '值', success: '成功', delete_cell: '删除选中的线或节点', - online_directly: '是否上线流程定义' + online_directly: '是否上线流程定义', + dag_name_empty: 'DAG图名称不能为空', + positive_integer: '请输入大于 0 的正整数', + prop_empty: '自定义参数prop不能为空', + prop_repeat: 'prop中有重复', + node_not_created: '未创建节点保存失败' }, node: { current_node_settings: '当前节点设置', diff --git a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts index 6b3d3bccb5..b177988635 100644 --- a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts +++ b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts @@ -139,7 +139,7 @@ export function querySimpleList(code: number): any { }) } -export function verifyName(params: NameReq, code: CodeReq): any { +export function verifyName(params: NameReq, code: number): any { return axios({ url: `/projects/${code}/process-definition/verify-name`, method: 'get', diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx index bef3fdf096..8962fcc281 100644 --- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx @@ -30,6 +30,8 @@ import { } from 'naive-ui' import { queryTenantList } from '@/service/modules/tenants' import { SaveForm, WorkflowDefinition } from './types' +import { useRoute } from 'vue-router' +import { verifyName } from '@/service/modules/process-definition' import './x6-style.scss' const props = { @@ -54,8 +56,10 @@ export default defineComponent({ props, emits: ['update:show', 'save'], setup(props, context) { + const route = useRoute() const { t } = useI18n() + const projectCode = Number(route.params.projectCode) const tenants = ref([]) const tenantsDropdown = computed(() => { if (tenants.value) { @@ -86,33 +90,80 @@ export default defineComponent({ const formRef = ref() const rule = { name: { - required: true + required: true, + message: t('project.dag.dag_name_empty') + }, + timeout: { + validator() { + if (formValue.value.timeoutFlag && formValue.value.timeout <= 0) { + return new Error(t('project.dag.positive_integer')) + } + } + }, + globalParams: { + validator() { + const props = new Set() + for (const param of formValue.value.globalParams) { + const prop = param.value + if (!prop) { + return new Error(t('project.dag.prop_empty')) + } + + if (props.has(prop)) { + return new Error(t('project.dag.prop_repeat')) + } + + props.add(prop) + } + } } } const onSubmit = () => { - context.emit('save', formValue.value) + formRef.value.validate(async (valid: any) => { + if (!valid) { + const params = { + name: formValue.value.name + } + if ( + props.definition?.processDefinition.name !== formValue.value.name + ) { + verifyName(params, projectCode) + .then(() => context.emit('save', formValue.value)) + .catch((error: any) => { + window.$message.error(error.message) + }) + } else { + context.emit('save', formValue.value) + } + } + }) } const onCancel = () => { context.emit('update:show', false) } - watch( - () => props.definition, - () => { - const process = props.definition?.processDefinition - if (process) { - formValue.value.name = process.name - formValue.value.description = process.description - formValue.value.tenantCode = process.tenantCode - if (process.timeout && process.timeout > 0) { - formValue.value.timeoutFlag = true - formValue.value.timeout = process.timeout - } - formValue.value.globalParams = process.globalParamList.map( - (param) => ({ key: param.prop, value: param.value }) - ) + const updateModalData = () => { + const process = props.definition?.processDefinition + if (process) { + formValue.value.name = process.name + formValue.value.description = process.description + formValue.value.tenantCode = process.tenantCode + if (process.timeout && process.timeout > 0) { + formValue.value.timeoutFlag = true + formValue.value.timeout = process.timeout } + formValue.value.globalParams = process.globalParamList.map((param) => ({ + key: param.prop, + value: param.value + })) } + } + + onMounted(() => updateModalData()) + + watch( + () => props.definition?.processDefinition, + () => updateModalData() ) return () => ( diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx index 4376486880..6f469baf7d 100644 --- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx @@ -25,6 +25,7 @@ import { watch, onBeforeUnmount } from 'vue' +import { useI18n } from 'vue-i18n' import DagToolbar from './dag-toolbar' import DagCanvas from './dag-canvas' import DagSidebar from './dag-sidebar' @@ -73,6 +74,7 @@ export default defineComponent({ props, emits: ['refresh', 'save'], setup(props, context) { + const { t } = useI18n() const theme = useThemeStore() // Whether the graph can be operated @@ -156,6 +158,11 @@ export default defineComponent({ const onSave = (saveForm: any) => { const edges = graph.value?.getEdges() || [] const nodes = graph.value?.getNodes() || [] + if (!nodes.length) { + window.$message.error(t('project.dag.node_not_created')) + saveModelToggle(false) + return + } const connects = getConnects(nodes, edges, taskDefinitions.value as any) const locations = getLocations(nodes) context.emit('save', { diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx index f2cc259848..cb2dcfd302 100644 --- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx @@ -75,10 +75,14 @@ export default defineComponent({ timeout: saveForm.timeoutFlag ? saveForm.timeout : 0 }, projectCode - ).then((res: any) => { - message.success(t('project.dag.success')) - router.push({ path: `/projects/${projectCode}/workflow-definition` }) - }) + ) + .then((res: any) => { + message.success(t('project.dag.success')) + router.push({ path: `/projects/${projectCode}/workflow-definition` }) + }) + .catch((error: any) => { + window.$message.error(error.message) + }) } return () => ( diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx index c14e225f47..b2aa4b3e45 100644 --- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx @@ -94,10 +94,14 @@ export default defineComponent({ }, code, projectCode - ).then((res: any) => { - message.success(t('project.dag.success')) - router.push({ path: `/projects/${projectCode}/workflow-definition` }) - }) + ) + .then((res: any) => { + message.success(t('project.dag.success')) + router.push({ path: `/projects/${projectCode}/workflow-definition` }) + }) + .catch((error: any) => { + window.$message.error(error.message) + }) } onMounted(() => {