This is an automated email from the ASF dual-hosted git repository.

songjian pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new dd3e290  [Feature][UI Next] Add the form of sql task to the module of 
next ui. (#8471)
dd3e290 is described below

commit dd3e2905dce907eb27558b97c1f06aa47d9ca9d5
Author: calvin <[email protected]>
AuthorDate: Mon Feb 21 18:33:57 2022 +0800

    [Feature][UI Next] Add the form of sql task to the module of next ui. 
(#8471)
    
    * add the form of sql task
    
    * add the form of sql task
    
    * add the form of sql task
    
    * add the component of input group
    
    * add the component of input group
    
    * The form of sql task is done
---
 dolphinscheduler-ui-next/docs/e2e/security.md      |   4 +-
 .../src/components/form/fields/index.ts            |   1 +
 .../src/components/form/fields/multi-input.ts      | 139 +++++++++++++
 .../src/components/form/types.ts                   |   1 +
 .../src/locales/modules/en_US.ts                   |  12 +-
 .../src/locales/modules/zh_CN.ts                   |  12 +-
 .../src/views/datasource/list/use-form.ts          |   2 -
 .../projects/task/components/node/fields/index.ts  |   4 +
 .../components/node/fields/use-datasource-type.ts  | 114 +++++++++++
 .../task/components/node/fields/use-datasource.ts  |  86 +++++++++
 .../task/components/node/fields/use-sql-type.ts    |  72 +++++++
 .../task/components/node/fields/use-sql.ts         | 214 +++++++++++++++++++++
 .../projects/task/components/node/format-data.ts   |  10 +
 .../projects/task/components/node/tasks/use-sql.ts |  95 +++++++++
 .../views/projects/task/components/node/types.ts   |  12 ++
 .../projects/task/components/node/use-task.ts      |   9 +
 16 files changed, 781 insertions(+), 6 deletions(-)

diff --git a/dolphinscheduler-ui-next/docs/e2e/security.md 
b/dolphinscheduler-ui-next/docs/e2e/security.md
index a7ac533..fb1927e 100644
--- a/dolphinscheduler-ui-next/docs/e2e/security.md
+++ b/dolphinscheduler-ui-next/docs/e2e/security.md
@@ -12,7 +12,7 @@ class:
 #### tenant manage
 
 | check              | class              |
-| ------------------ |--------------------|
+| ------------------ | ------------------ |
 | :white_check_mark: | items              |
 |                    | el-popconfirm      |
 |                    | el-button--primary |
@@ -29,7 +29,7 @@ class:
 #### user manage
 
 | check              | class               |
-| ------------------ |---------------------|
+| ------------------ | ------------------- |
 | :white_check_mark: | items               |
 |                    | el-popconfirm       |
 |                    | el-button--primary  |
diff --git a/dolphinscheduler-ui-next/src/components/form/fields/index.ts 
b/dolphinscheduler-ui-next/src/components/form/fields/index.ts
index 82ca19d..abf4220 100644
--- a/dolphinscheduler-ui-next/src/components/form/fields/index.ts
+++ b/dolphinscheduler-ui-next/src/components/form/fields/index.ts
@@ -24,3 +24,4 @@ export { renderInputNumber } from './input-number'
 export { renderSelect } from './select'
 export { renderCheckbox } from './checkbox'
 export { renderTreeSelect } from './tree-select'
+export { renderMultiInput } from './multi-input'
diff --git a/dolphinscheduler-ui-next/src/components/form/fields/multi-input.ts 
b/dolphinscheduler-ui-next/src/components/form/fields/multi-input.ts
new file mode 100644
index 0000000..1ffbd48
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/fields/multi-input.ts
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineComponent, h, unref, renderSlot } from 'vue'
+import { useFormItem } from 'naive-ui/es/_mixins'
+import {
+  NFormItemGi,
+  NSpace,
+  NButton,
+  NGrid,
+  NGridItem,
+  NInput
+} from 'naive-ui'
+import { PlusOutlined, DeleteOutlined } from '@vicons/antd'
+import type { IJsonItem, FormItemRule } from '../types'
+
+const MultiInput = defineComponent({
+  name: 'MultiInput',
+  emits: ['add'],
+  setup(props, ctx) {
+    const formItem = useFormItem({})
+    const onAdd = () => void ctx.emit('add')
+
+    return { onAdd, disabled: formItem.mergedDisabledRef }
+  },
+  render() {
+    const { disabled, $slots, onAdd } = this
+
+    return h(
+      NSpace,
+      { vertical: true, style: { width: '100%' } },
+      {
+        default: () => {
+          return [
+            renderSlot($slots, 'default', { disabled }),
+            h(
+              NButton,
+              {
+                circle: true,
+                size: 'small',
+                type: 'info',
+                disabled,
+                onClick: onAdd
+              },
+              {
+                icon: () => h(PlusOutlined)
+              }
+            )
+          ]
+        }
+      }
+    )
+  }
+})
+
+export function renderMultiInput(
+  item: IJsonItem,
+  fields: { [field: string]: any },
+  rules: { [key: string]: FormItemRule }[]
+) {
+  let ruleItem: { [key: string]: FormItemRule } = {}
+
+  // the fields is the data of the task definition.
+  // the item is the options of this component in the form.
+
+  const getChild = (value: string, i: number) => {
+    return h(
+      NFormItemGi,
+      {
+        showLabel: false,
+        path: `${item.field}[${i}]`,
+        span: unref(item.span)
+      },
+      () =>
+        h(NInput, {
+          ...item.props,
+          value: value,
+          onUpdateValue: (value: string) => void (fields[item.field][i] = 
value)
+        })
+    )
+  }
+
+  //initialize the component by using data
+  const getChildren = ({ disabled }: { disabled: boolean }) =>
+    fields[item.field].map((value: string, i: number) => {
+      return h(NGrid, { xGap: 10 }, () => [
+        getChild(value, i),
+        h(
+          NGridItem,
+          {
+            span: 2
+          },
+          () =>
+            h(
+              NButton,
+              {
+                circle: true,
+                type: 'error',
+                size: 'small',
+                disabled,
+                onClick: () => {
+                  fields[item.field].splice(i, 1)
+                }
+              },
+              {
+                icon: () => h(DeleteOutlined)
+              }
+            )
+        )
+      ])
+    })
+
+  return h(
+    MultiInput,
+    {
+      name: item.field,
+      onAdd: () => {
+        fields[item.field].push('')
+      }
+    },
+    {
+      default: getChildren
+    }
+  )
+}
diff --git a/dolphinscheduler-ui-next/src/components/form/types.ts 
b/dolphinscheduler-ui-next/src/components/form/types.ts
index 4d4a015..f7b350d 100644
--- a/dolphinscheduler-ui-next/src/components/form/types.ts
+++ b/dolphinscheduler-ui-next/src/components/form/types.ts
@@ -34,6 +34,7 @@ type IType =
   | 'select'
   | 'checkbox'
   | 'tree-select'
+  | 'multi-input'
 
 interface IOption extends SelectOption, TreeSelectOption {
   label: string
diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts 
b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index 77549f0..07d1320 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -672,7 +672,17 @@ const project = {
     body_not_contains: 'Content does not contain',
     http_parameters_position: 'Http Parameters Position',
     target_task_name: 'Target Task Name',
-    target_task_name_tips: 'Please enter the Pigeon task name'
+    target_task_name_tips: 'Please enter the Pigeon task name',
+    datasource_type: 'Datasource types',
+    datasource: 'Datasource instances',
+    sql_type: 'SQL Type',
+    sql_type_query: 'Query',
+    sql_type_non_query: 'Non Query',
+    sql_statement: 'SQL Statement',
+    pre_sql_statement: 'Pre SQL Statement',
+    post_sql_statement: 'Post SQL Statement',
+    sql_input_placeholder: 'Please enter non-query sql.',
+    sql_empty_tips: 'The sql can not be empty.'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts 
b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index 6ee70b4..8184d8a 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -664,7 +664,17 @@ const project = {
     body_not_contains: '内容不包含',
     http_parameters_position: '参数位置',
     target_task_name: '目标任务名',
-    target_task_name_tips: '请输入Pigeon任务名'
+    target_task_name_tips: '请输入Pigeon任务名',
+    datasource_type: '数据源类型',
+    datasource: '数据源实例',
+    sql_type: 'SQL类型',
+    sql_type_query: '查询',
+    sql_type_non_query: '非查询',
+    sql_statement: 'SQL语句',
+    pre_sql_statement: '前置SQL语句',
+    post_sql_statement: '后置SQL语句',
+    sql_input_placeholder: '请输入非查询SQL语句',
+    sql_empty_tips: '语句不能为空'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/views/datasource/list/use-form.ts 
b/dolphinscheduler-ui-next/src/views/datasource/list/use-form.ts
index 83eec4f..1f091be 100644
--- a/dolphinscheduler-ui-next/src/views/datasource/list/use-form.ts
+++ b/dolphinscheduler-ui-next/src/views/datasource/list/use-form.ts
@@ -205,8 +205,6 @@ const datasourceType: IDataBaseOptionKeys = {
   }
 }
 
-console.log(Object.values(datasourceType))
-
 export const datasourceTypeList: IDataBaseOption[] = Object.values(
   datasourceType
 ).map((item) => {
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts
index 5eefb20..69216c7 100644
--- 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts
@@ -30,9 +30,13 @@ export { useTaskType } from './use-task-type'
 export { useProcessName } from './use-process-name'
 export { useChildNode } from './use-child-node'
 export { useTargetTaskName } from './use-target-task-name'
+export { useDatasourceType } from './use-datasource-type'
+export { useDatasource } from './use-datasource'
+export { useSqlType } from './use-sql-type'
 
 export { useShell } from './use-shell'
 export { useSpark } from './use-spark'
 export { useMr } from './use-mr'
 export { useFlink } from './use-flink'
 export { useHttp } from './use-http'
+export { useSql } from './use-sql'
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource-type.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource-type.ts
new file mode 100644
index 0000000..9b83a35
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource-type.ts
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ref, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { IJsonItem } from '../types'
+import { number } from 'echarts'
+
+export function useDatasourceType(model: { [field: string]: any }): IJsonItem {
+  const { t } = useI18n()
+
+  const options = ref([] as { label: string; value: string }[])
+  const loading = ref(false)
+
+  const datasourceTypes = [
+    {
+      id: 0,
+      code: 'MYSQL',
+      disabled: false
+    },
+    {
+      id: 1,
+      code: 'POSTGRESQL',
+      disabled: false
+    },
+    {
+      id: 2,
+      code: 'HIVE',
+      disabled: false
+    },
+    {
+      id: 3,
+      code: 'SPARK',
+      disabled: false
+    },
+    {
+      id: 4,
+      code: 'CLICKHOUSE',
+      disabled: false
+    },
+    {
+      id: 5,
+      code: 'ORACLE',
+      disabled: false
+    },
+    {
+      id: 6,
+      code: 'SQLSERVER',
+      disabled: false
+    },
+    {
+      id: 7,
+      code: 'DB2',
+      disabled: false
+    },
+    {
+      id: 8,
+      code: 'PRESTO',
+      disabled: false
+    }
+  ]
+
+  const getDatasourceTypes = async () => {
+    if (loading.value) return
+    loading.value = true
+    try {
+      options.value = datasourceTypes
+        .filter((item) => !item.disabled)
+        .map((item) => ({ label: item.code, value: item.code }))
+      loading.value = false
+    } catch (err) {
+      loading.value = false
+    }
+  }
+
+  const onChange = (type: string) => {
+    model.type = type
+  }
+
+  onMounted(() => {
+    getDatasourceTypes()
+  })
+  return {
+    type: 'select',
+    field: 'datasourceType',
+    span: 12,
+    name: t('project.node.datasource_type'),
+    props: {
+      loading: loading,
+      'on-update:value': onChange
+    },
+    options: options,
+    validate: {
+      trigger: ['input', 'blur'],
+      required: true,
+      message: t('project.node.worker_group_tips')
+    },
+    value: model.type
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource.ts
new file mode 100644
index 0000000..f34636a
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-datasource.ts
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ref, onMounted, watch } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { queryDataSourceList } from '@/service/modules/data-source'
+import type { IJsonItem } from '../types'
+import { TypeReq } from '@/service/modules/data-source/types'
+import { find } from 'lodash'
+
+export function useDatasource(model: { [field: string]: any }): IJsonItem {
+  const { t } = useI18n()
+
+  const options = ref([] as { label: string; value: string }[])
+  const loading = ref(false)
+  const defaultValue = ref(null)
+
+  const getDatasources = async () => {
+    if (loading.value) return
+    loading.value = true
+    try {
+      await refreshOptions()
+      loading.value = false
+    } catch (err) {
+      loading.value = false
+    }
+  }
+
+  const refreshOptions = async () => {
+    const params = { type: model.type } as TypeReq
+    const res = await queryDataSourceList(params)
+    defaultValue.value = null
+    options.value = []
+
+    res.map((item: any) => {
+      options.value.push({ label: item.name, value: String(item.id) })
+    })
+    if (options.value && model.datasource) {
+      let item = find(options.value, { value: String(model.datasource) })
+      if (!item) {
+        model.datasource = null
+      }
+    }
+  }
+
+  watch(
+    () => model.type,
+    () => {
+      if (model.type) {
+        refreshOptions()
+      }
+    }
+  )
+
+  onMounted(() => {
+    getDatasources()
+  })
+  return {
+    type: 'select',
+    field: 'datasource',
+    span: 12,
+    name: t('project.node.datasource'),
+    props: {
+      loading: loading
+    },
+    options: options,
+    validate: {
+      trigger: ['input', 'blur'],
+      required: true
+    }
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql-type.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql-type.ts
new file mode 100644
index 0000000..e46c416
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql-type.ts
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ref, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { IJsonItem } from '../types'
+
+export function useSqlType(model: { [field: string]: any }): IJsonItem {
+  const { t } = useI18n()
+
+  const options = ref([] as { label: string; value: string }[])
+  const loading = ref(false)
+
+  const sqlTypes = [
+    {
+      id: '0',
+      code: t('project.node.sql_type_query')
+    },
+    {
+      id: '1',
+      code: t('project.node.sql_type_non_query')
+    }
+  ]
+
+  const getSqlTypes = async () => {
+    if (loading.value) return
+    loading.value = true
+    try {
+      options.value = sqlTypes.map((item) => ({
+        label: item.code,
+        value: item.id
+      }))
+      loading.value = false
+    } catch (err) {
+      loading.value = false
+    }
+  }
+
+  onMounted(() => {
+    getSqlTypes()
+  })
+
+  return {
+    type: 'select',
+    field: 'sqlType',
+    span: 12,
+    name: t('project.node.sql_type'),
+    props: {
+      loading: loading
+    },
+    options: options,
+    validate: {
+      trigger: ['input', 'blur'],
+      required: true
+    },
+    value: '0'
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql.ts
new file mode 100644
index 0000000..21e67af
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sql.ts
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ref, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { queryResourceList } from '@/service/modules/resources'
+import type { IJsonItem } from '../types'
+
+export function useSql(model: { [field: string]: any }): IJsonItem[] {
+  const { t } = useI18n()
+  const options = ref([])
+
+  const loading = ref(false)
+
+  const getResourceList = async () => {
+    if (loading.value) return
+    loading.value = true
+    try {
+      const res = await queryResourceList({ type: 'FILE' })
+      removeUselessChildren(res)
+      options.value = res || []
+      loading.value = false
+    } catch (err) {
+      loading.value = false
+    }
+  }
+
+  onMounted(() => {
+    getResourceList()
+  })
+
+  return [
+    {
+      type: 'editor',
+      field: 'sql',
+      name: t('project.node.sql_statement'),
+      validate: {
+        trigger: ['input', 'trigger'],
+        required: true,
+        message: t('project.node.sql_empty_tips')
+      }
+    },
+    {
+      type: 'tree-select',
+      field: 'resourceList',
+      name: t('project.node.resources'),
+      options,
+      props: {
+        multiple: true,
+        checkable: true,
+        cascade: true,
+        showPath: true,
+        checkStrategy: 'child',
+        placeholder: t('project.node.resources_tips'),
+        keyField: 'id',
+        labelField: 'name',
+        loading
+      }
+    },
+    {
+      type: 'custom-parameters',
+      field: 'localParams',
+      name: t('project.node.custom_parameters'),
+      children: [
+        {
+          type: 'input',
+          field: 'prop',
+          span: 6,
+          props: {
+            placeholder: t('project.node.prop_tips'),
+            maxLength: 256
+          },
+          validate: {
+            trigger: ['input', 'blur'],
+            required: true,
+            validator(validate: any, value: string) {
+              if (!value) {
+                return new Error(t('project.node.prop_tips'))
+              }
+
+              const sameItems = model.localParams.filter(
+                (item: { prop: string }) => item.prop === value
+              )
+
+              if (sameItems.length > 1) {
+                return new Error(t('project.node.prop_repeat'))
+              }
+            }
+          }
+        },
+        {
+          type: 'select',
+          field: 'direct',
+          span: 4,
+          options: DIRECT_LIST,
+          value: 'IN'
+        },
+        {
+          type: 'select',
+          field: 'type',
+          span: 6,
+          options: TYPE_LIST,
+          value: 'VARCHAR'
+        },
+        {
+          type: 'input',
+          field: 'value',
+          span: 6,
+          props: {
+            placeholder: t('project.node.value_tips'),
+            maxLength: 256
+          }
+        }
+      ]
+    },
+    {
+      type: 'multi-input',
+      field: 'preStatements',
+      name: t('project.node.pre_sql_statement'),
+      span: 22,
+      props: {
+        placeholder: t('project.node.sql_input_placeholder'),
+        type: 'textarea',
+        autosize: { minRows: 1 }
+      }
+    },
+    {
+      type: 'multi-input',
+      field: 'postStatements',
+      name: t('project.node.post_sql_statement'),
+      span: 22,
+      props: {
+        placeholder: t('project.node.sql_input_placeholder'),
+        type: 'textarea',
+        autosize: { minRows: 1 }
+      }
+    }
+  ]
+}
+
+function removeUselessChildren(list: { children?: [] }[]) {
+  if (!list.length) return
+  list.forEach((item) => {
+    if (!item.children) return
+    if (item.children.length === 0) {
+      delete item.children
+      return
+    }
+    removeUselessChildren(item.children)
+  })
+}
+
+export const TYPE_LIST = [
+  {
+    value: 'VARCHAR',
+    label: 'VARCHAR'
+  },
+  {
+    value: 'INTEGER',
+    label: 'INTEGER'
+  },
+  {
+    value: 'LONG',
+    label: 'LONG'
+  },
+  {
+    value: 'FLOAT',
+    label: 'FLOAT'
+  },
+  {
+    value: 'DOUBLE',
+    label: 'DOUBLE'
+  },
+  {
+    value: 'DATE',
+    label: 'DATE'
+  },
+  {
+    value: 'TIME',
+    label: 'TIME'
+  },
+  {
+    value: 'TIMESTAMP',
+    label: 'TIMESTAMP'
+  },
+  {
+    value: 'BOOLEAN',
+    label: 'BOOLEAN'
+  }
+]
+
+export const DIRECT_LIST = [
+  {
+    value: 'IN',
+    label: 'IN'
+  },
+  {
+    value: 'OUT',
+    label: 'OUT'
+  }
+]
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts
index b98e882..227c3db 100644
--- 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts
@@ -67,6 +67,15 @@ export function formatParams(data: INodeData): {
     taskParams.socketTimeout = data.socketTimeout
   }
 
+  if (data.taskType === 'SQL') {
+    taskParams.type = data.type
+    taskParams.datasource = data.datasource
+    taskParams.sql = data.sql
+    taskParams.sqlType = data.sqlType
+    taskParams.preStatements = data.preStatements
+    taskParams.postStatements = data.postStatements
+  }
+
   const params = {
     processDefinitionCode: data.processName ? String(data.processName) : '',
     upstreamCodes: data?.preTasks?.join(','),
@@ -125,6 +134,7 @@ export function formatModel(data: ITaskData) {
     timeoutNotifyStrategy: [data.timeoutNotifyStrategy] || [],
     localParams: data.taskParams?.localParams || []
   } as INodeData
+
   if (data.timeoutNotifyStrategy === 'WARNFAILED') {
     params.timeoutNotifyStrategy = ['WARN', 'FAILED']
   }
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-sql.ts
 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-sql.ts
new file mode 100644
index 0000000..242fbef
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-sql.ts
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive } from 'vue'
+import * as Fields from '../fields/index'
+import type { IJsonItem, INodeData } from '../types'
+import { ITaskData } from '../types'
+
+export function useSql({
+  projectCode,
+  from = 0,
+  readonly,
+  data
+}: {
+  projectCode: number
+  from?: number
+  readonly?: boolean
+  data?: ITaskData
+}) {
+  const model = reactive({
+    name: '',
+    taskType: 'SQL',
+    flag: 'YES',
+    description: '',
+    timeoutFlag: false,
+    localParams: [],
+    environmentCode: null,
+    failRetryInterval: 1,
+    failRetryTimes: 0,
+    workerGroup: 'default',
+    delayTime: 0,
+    timeout: 30,
+    type: data?.taskParams?.type ? data?.taskParams?.type : 'MYSQL',
+    datasource: data?.taskParams?.datasource,
+    sql: data?.taskParams?.sql,
+    sqlType: data?.taskParams?.sqlType,
+    preStatements: data?.taskParams?.preStatements
+      ? data?.taskParams?.preStatements
+      : [],
+    postStatements: data?.taskParams?.postStatements
+      ? data?.taskParams?.postStatements
+      : []
+  } as INodeData)
+
+  let extra: IJsonItem[] = []
+  if (from === 1) {
+    extra = [
+      Fields.useTaskType(model, readonly),
+      Fields.useProcessName({
+        model,
+        projectCode,
+        isCreate: !data?.id,
+        from,
+        processName: data?.processName,
+        code: data?.code
+      })
+    ]
+  }
+
+  return {
+    json: [
+      Fields.useName(),
+      ...extra,
+      Fields.useRunFlag(),
+      Fields.useDescription(),
+      Fields.useTaskPriority(),
+      Fields.useWorkerGroup(),
+      Fields.useEnvironmentName(model, !model.id),
+      ...Fields.useTaskGroup(model, projectCode),
+      ...Fields.useFailed(),
+      Fields.useDelayTime(model),
+      ...Fields.useTimeoutAlarm(model),
+      Fields.useDatasourceType(model),
+      Fields.useDatasource(model),
+      Fields.useSqlType(model),
+      ...Fields.useSql(model),
+      Fields.usePreTasks(model)
+    ] as IJsonItem[],
+    model
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts
index 00f45a9..6895827 100644
--- a/dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts
@@ -70,6 +70,12 @@ interface ITaskParams {
   condition?: string
   connectTimeout?: number
   socketTimeout?: number
+  type?: string
+  datasource?: string
+  sql?: string
+  sqlType?: string
+  preStatements?: string[]
+  postStatements?: string[]
 }
 
 type ITaskType = TaskType
@@ -99,6 +105,12 @@ interface INodeData extends Omit<ITaskParams, 
'resourceList' | 'mainJar'> {
   resourceList?: number[]
   mainJar?: number
   timeoutSetting?: boolean
+  type?: string
+  datasource?: string
+  sql?: string
+  sqlType?: string
+  preStatements?: string[]
+  postStatements?: string[]
 }
 
 interface ITaskData
diff --git 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts
index 89b9882..7b67cdb 100644
--- 
a/dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts
+++ 
b/dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts
@@ -23,6 +23,7 @@ import { usePython } from './tasks/use-python'
 import { useSpark } from './tasks/use-spark'
 import { useMr } from './tasks/use-mr'
 import { useHttp } from './tasks/use-http'
+import { useSql } from './tasks/use-sql'
 import { IJsonItem, INodeData, ITaskData } from './types'
 
 export function useTask({
@@ -102,5 +103,13 @@ export function useTask({
       data
     })
   }
+  if (taskType === 'SQL') {
+    node = useSql({
+      projectCode,
+      from,
+      readonly,
+      data
+    })
+  }
   return node
 }

Reply via email to