This is an automated email from the ASF dual-hosted git repository.
songjian pushed a commit to branch add_canvas_job_define
in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git
The following commit(s) were added to refs/heads/add_canvas_job_define by this
push:
new 153e7b4f [Feat][UI] Add virtual table function.
153e7b4f is described below
commit 153e7b4f7e0124092fdf8f4a765d0aad6f580cf0
Author: songjianet <[email protected]>
AuthorDate: Wed Jun 7 09:38:58 2023 +0800
[Feat][UI] Add virtual table function.
---
.../src/layouts/dashboard/header/menu/use-menu.ts | 4 +
seatunnel-ui/src/locales/en_US/datasource.ts | 1 +
seatunnel-ui/src/locales/en_US/index.ts | 4 +-
seatunnel-ui/src/locales/en_US/menu.ts | 3 +-
seatunnel-ui/src/locales/en_US/virtual-tables.ts | 63 ++++
seatunnel-ui/src/locales/zh_CN/datasource.ts | 1 +
seatunnel-ui/src/locales/zh_CN/index.ts | 4 +-
seatunnel-ui/src/locales/zh_CN/menu.ts | 3 +-
seatunnel-ui/src/locales/zh_CN/virtual-tables.ts | 62 ++++
seatunnel-ui/src/router/routes.ts | 4 +-
.../zh_CN/index.ts => router/virtual-tables.ts} | 42 +--
.../menu.ts => service/virtual-tables/index.ts} | 17 +-
.../menu.ts => service/virtual-tables/types.ts} | 11 -
seatunnel-ui/src/views/datasource/list/index.tsx | 2 +-
.../src/views/datasource/list/use-columns.ts | 2 +
seatunnel-ui/src/views/virtual-tables/detail.tsx | 198 +++++++++++++
.../src/views/virtual-tables/index.module.scss | 81 +++++
.../src/views/virtual-tables/list/index.tsx | 120 ++++++++
.../src/views/virtual-tables/list/use-columns.ts | 115 ++++++++
.../src/views/virtual-tables/list/use-table.ts | 114 +++++++
.../src/views/virtual-tables/step-one-form.tsx | 144 +++++++++
.../virtual-tables/step-three-params.tsx} | 55 ++--
.../src/views/virtual-tables/step-two-form.tsx | 117 ++++++++
.../src/views/virtual-tables/step-two-table.tsx | 327 +++++++++++++++++++++
.../menu.ts => views/virtual-tables/types.ts} | 19 +-
.../src/views/virtual-tables/use-detail.ts | 184 ++++++++++++
26 files changed, 1619 insertions(+), 78 deletions(-)
diff --git a/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
b/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
index ebdc7994..509bc8b5 100644
--- a/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
+++ b/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
@@ -39,6 +39,10 @@ export function useMenu() {
label: () => h(NEllipsis, null, { default: () => t('menu.datasource') }),
key: 'datasource'
},
+ {
+ label: () => h(NEllipsis, null, { default: () =>
t('menu.virtual_tables') }),
+ key: 'virtual-tables'
+ },
{
label: () => h(NEllipsis, null, { default: () => t('menu.user_manage')
}),
key: 'user-manage'
diff --git a/seatunnel-ui/src/locales/en_US/datasource.ts
b/seatunnel-ui/src/locales/en_US/datasource.ts
index 6edf737c..e811af28 100644
--- a/seatunnel-ui/src/locales/en_US/datasource.ts
+++ b/seatunnel-ui/src/locales/en_US/datasource.ts
@@ -16,6 +16,7 @@
*/
export default {
+ id: 'Id',
datasource: 'DataSource',
create_datasource: 'Create DataSource',
choose_datasource_type: 'Choose DataSource Type',
diff --git a/seatunnel-ui/src/locales/en_US/index.ts
b/seatunnel-ui/src/locales/en_US/index.ts
index 6d57ce9d..6a25d3dc 100644
--- a/seatunnel-ui/src/locales/en_US/index.ts
+++ b/seatunnel-ui/src/locales/en_US/index.ts
@@ -25,6 +25,7 @@ import jobs from '@/locales/en_US/jobs'
import tasks from '@/locales/en_US/tasks'
import setting from '@/locales/en_US/setting'
import datasource from '@/locales/en_US/datasource'
+import virtual_tables from '@/locales/en_US/virtual-tables'
export default {
login,
@@ -36,5 +37,6 @@ export default {
jobs,
tasks,
setting,
- datasource
+ datasource,
+ virtual_tables
}
diff --git a/seatunnel-ui/src/locales/en_US/menu.ts
b/seatunnel-ui/src/locales/en_US/menu.ts
index 800541f5..f3bd9587 100644
--- a/seatunnel-ui/src/locales/en_US/menu.ts
+++ b/seatunnel-ui/src/locales/en_US/menu.ts
@@ -23,5 +23,6 @@ export default {
setting: 'Setting',
logout: 'Logout',
tasks: 'Tasks',
- datasource: 'Datasource'
+ datasource: 'Datasource',
+ virtual_tables: 'Virtual Tables'
}
diff --git a/seatunnel-ui/src/locales/en_US/virtual-tables.ts
b/seatunnel-ui/src/locales/en_US/virtual-tables.ts
new file mode 100644
index 00000000..9b0650ce
--- /dev/null
+++ b/seatunnel-ui/src/locales/en_US/virtual-tables.ts
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+export default {
+ virtual_tables: 'Virtual Tables',
+ create_virtual_tables: 'Create Virtual Tables',
+ edit_virtual_tables: 'Edit Virtual Tables',
+ source_type: 'Source Type',
+ source_type_tips: 'Please select a source type',
+ source_name: 'Source Name',
+ source_name_tips: 'Please enter source name',
+ table_name: 'Table Name',
+ database_name: 'Database Name',
+ creator: 'Creator',
+ creation_time: 'Creation Time',
+ updater: 'Updater',
+ update_time: 'Update Time',
+ operation: 'Operation',
+ edit: 'Edit',
+ delete: 'Delete',
+ confirm: 'Confirm',
+ delete_confirm: 'Delete?',
+ cancel: 'Cancel',
+ configure: 'Configure',
+ model: 'Model',
+ complete: 'Complete',
+ virtual_tables_name: 'Virtual Table Name',
+ virtual_tables_name_tips: 'Please enter a virtual table name',
+ next_step: 'Next Step',
+ previous_step: 'Previous Step',
+ table_structure: 'Table Structure',
+ add: 'Add a row',
+ field_name: 'Field Name',
+ field_name_tips: 'Please enter a field name',
+ field_type: 'Field Type',
+ is_null: 'Null',
+ is_primary_key: 'Primary Key',
+ description: 'Field Description',
+ yes: 'Yes',
+ no: 'No',
+ warning: 'Warning',
+ close_confirm_tips:
+ 'This operation will lose the currently created virtual table',
+ save_data_tips: 'Please save the data in the table',
+ table_data_required_tips: 'Please add a record to the table',
+ default_value: 'Default Value',
+ create: 'Create',
+ search: 'Search'
+}
diff --git a/seatunnel-ui/src/locales/zh_CN/datasource.ts
b/seatunnel-ui/src/locales/zh_CN/datasource.ts
index 6aaf46bd..f8321b5f 100644
--- a/seatunnel-ui/src/locales/zh_CN/datasource.ts
+++ b/seatunnel-ui/src/locales/zh_CN/datasource.ts
@@ -16,6 +16,7 @@
*/
export default {
+ id: 'Id',
datasource: '数据源',
create_datasource: '创建源',
choose_datasource_type: '选择源类型',
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts
b/seatunnel-ui/src/locales/zh_CN/index.ts
index c3e11f4a..8ecf70c4 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/locales/zh_CN/index.ts
@@ -25,6 +25,7 @@ import jobs from '@/locales/zh_CN/jobs'
import tasks from '@/locales/zh_CN/tasks'
import setting from '@/locales/zh_CN/setting'
import datasource from '@/locales/zh_CN/datasource'
+import virtual_tables from '@/locales/zh_CN/virtual-tables'
export default {
login,
@@ -36,5 +37,6 @@ export default {
jobs,
tasks,
setting,
- datasource
+ datasource,
+ virtual_tables
}
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts
b/seatunnel-ui/src/locales/zh_CN/menu.ts
index 5270249f..1ab59deb 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/locales/zh_CN/menu.ts
@@ -23,5 +23,6 @@ export default {
setting: '设置',
logout: '登出',
tasks: '任务',
- datasource: '数据源'
+ datasource: '数据源',
+ virtual_tables: '虚拟表'
}
diff --git a/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts
b/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts
new file mode 100644
index 00000000..f7adb43f
--- /dev/null
+++ b/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+export default {
+ virtual_tables: '虚拟表',
+ create_virtual_tables: '创建虚拟表',
+ edit_virtual_tables: '编辑虚拟表',
+ source_type: '源类型',
+ source_type_tips: '请选择源类型',
+ source_name: '源名称',
+ source_name_tips: '请输入源名称',
+ table_name: '表名',
+ database_name: '库名',
+ creator: '创建人',
+ creation_time: '创建时间',
+ updater: '修改人',
+ update_time: '修改时间',
+ operation: '操作',
+ edit: '编辑',
+ delete: '删除',
+ confirm: '确定',
+ delete_confirm: '删除?',
+ cancel: '取消',
+ configure: '配置',
+ model: '模型',
+ complete: '完成',
+ virtual_tables_name: '虚拟表名',
+ virtual_tables_name_tips: '请输入虚拟表名',
+ next_step: '下一步',
+ previous_step: '上一步',
+ table_structure: '表结构',
+ add: '添加一行',
+ field_name: '字段名称',
+ field_name_tips: '请输入字段名称',
+ field_type: '字段类型',
+ is_null: '非空',
+ is_primary_key: '主键',
+ description: '字段描述',
+ yes: '是',
+ no: '否',
+ warning: '警告',
+ close_confirm_tips: '此操作会丢失当前创建的虚拟表',
+ save_data_tips: '请保存表格中的数据',
+ table_data_required_tips: '请在表结构中添加数据',
+ default_value: '默认值',
+ create: '创建',
+ search: '搜索'
+}
diff --git a/seatunnel-ui/src/router/routes.ts
b/seatunnel-ui/src/router/routes.ts
index 15d9eeff..121ba1ec 100644
--- a/seatunnel-ui/src/router/routes.ts
+++ b/seatunnel-ui/src/router/routes.ts
@@ -21,6 +21,7 @@ import jobs from '@/router/jobs'
import tasks from '@/router/tasks'
import userManage from '@/router/user-manage'
import datasource from '@/router/datasource'
+import virtualTables from '@/router/virtual-tables'
import type { RouteRecordRaw } from 'vue-router'
import type { Component } from 'vue'
@@ -36,7 +37,8 @@ const basePage: RouteRecordRaw[] = [
jobs,
tasks,
userManage,
- datasource
+ datasource,
+ virtualTables
]
const loginPage: RouteRecordRaw[] = [
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts
b/seatunnel-ui/src/router/virtual-tables.ts
similarity index 57%
copy from seatunnel-ui/src/locales/zh_CN/index.ts
copy to seatunnel-ui/src/router/virtual-tables.ts
index c3e11f4a..9224d206 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/router/virtual-tables.ts
@@ -15,26 +15,28 @@
* limitations under the License.
*/
-import login from '@/locales/zh_CN/login'
-import menu from '@/locales/zh_CN/menu'
-import modal from '@/locales/zh_CN/modal'
-import user_manage from '@/locales/zh_CN/user-manage'
-import data_pipes from '@/locales/zh_CN/data-pipes'
-import log from '@/locales/zh_CN/log'
-import jobs from '@/locales/zh_CN/jobs'
-import tasks from '@/locales/zh_CN/tasks'
-import setting from '@/locales/zh_CN/setting'
-import datasource from '@/locales/zh_CN/datasource'
+import utils from '@/utils'
+import type { Component } from 'vue'
+
+const modules = import.meta.glob('/src/views/**/**.tsx')
+const components: { [key: string]: Component } = utils.mapping(modules)
export default {
- login,
- menu,
- modal,
- user_manage,
- data_pipes,
- log,
- jobs,
- tasks,
- setting,
- datasource
+ path: '/virtual-tables',
+ name: 'virtual-tables',
+ meta: {
+ title: 'virtual-tables'
+ },
+ redirect: { name: 'virtual-tables-list' },
+ component: () => import('@/layouts/dashboard'),
+ children: [
+ {
+ path: '/virtual-tables/list',
+ name: 'virtual-tables-list',
+ component: components['virtual-tables-list'],
+ meta: {
+ title: 'virtual-tables-list'
+ }
+ }
+ ]
}
diff --git a/seatunnel-ui/src/locales/en_US/menu.ts
b/seatunnel-ui/src/service/virtual-tables/index.ts
similarity index 80%
copy from seatunnel-ui/src/locales/en_US/menu.ts
copy to seatunnel-ui/src/service/virtual-tables/index.ts
index 800541f5..1943eab2 100644
--- a/seatunnel-ui/src/locales/en_US/menu.ts
+++ b/seatunnel-ui/src/service/virtual-tables/index.ts
@@ -15,13 +15,12 @@
* limitations under the License.
*/
-export default {
- data_pipes: 'Data Pipes',
- jobs: 'Jobs',
- user_manage: 'User Manage',
- help: 'Help',
- setting: 'Setting',
- logout: 'Logout',
- tasks: 'Tasks',
- datasource: 'Datasource'
+import { axios } from '@/service/service'
+
+export function virtualTableList(params: any): any {
+ return axios({
+ url: '/virtual_table/list',
+ method: 'get',
+ params
+ })
}
diff --git a/seatunnel-ui/src/locales/en_US/menu.ts
b/seatunnel-ui/src/service/virtual-tables/types.ts
similarity index 80%
copy from seatunnel-ui/src/locales/en_US/menu.ts
copy to seatunnel-ui/src/service/virtual-tables/types.ts
index 800541f5..3e7c6c26 100644
--- a/seatunnel-ui/src/locales/en_US/menu.ts
+++ b/seatunnel-ui/src/service/virtual-tables/types.ts
@@ -14,14 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-export default {
- data_pipes: 'Data Pipes',
- jobs: 'Jobs',
- user_manage: 'User Manage',
- help: 'Help',
- setting: 'Setting',
- logout: 'Logout',
- tasks: 'Tasks',
- datasource: 'Datasource'
-}
diff --git a/seatunnel-ui/src/views/datasource/list/index.tsx
b/seatunnel-ui/src/views/datasource/list/index.tsx
index 70232dd3..05275749 100644
--- a/seatunnel-ui/src/views/datasource/list/index.tsx
+++ b/seatunnel-ui/src/views/datasource/list/index.tsx
@@ -142,7 +142,7 @@ const DatasourceList = defineComponent({
)
}}
</NCard>
- <NCard title='' class={styles['mt-8']}>
+ <NCard>
<NDataTable
row-class-name='data-source-items'
columns={columns}
diff --git a/seatunnel-ui/src/views/datasource/list/use-columns.ts
b/seatunnel-ui/src/views/datasource/list/use-columns.ts
index a46df1c4..15bae636 100644
--- a/seatunnel-ui/src/views/datasource/list/use-columns.ts
+++ b/seatunnel-ui/src/views/datasource/list/use-columns.ts
@@ -19,11 +19,13 @@ import { h } from 'vue'
import { useI18n } from 'vue-i18n'
import { NPopover, NButton, NSpace } from 'naive-ui'
import JsonHighlight from '../components/json-highlight'
+import { getTableColumn } from '@/common/table'
export function useColumns(onCallback: Function) {
const { t } = useI18n()
const getColumns = () => {
return [
+ ...getTableColumn([{ key: 'id', title: t('datasource.id') }]),
{
title: t('datasource.datasource_name'),
key: 'datasourceName'
diff --git a/seatunnel-ui/src/views/virtual-tables/detail.tsx
b/seatunnel-ui/src/views/virtual-tables/detail.tsx
new file mode 100644
index 00000000..7434d8dc
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/detail.tsx
@@ -0,0 +1,198 @@
+/*
+ * 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 } from 'vue'
+import {
+ NSpace,
+ NBreadcrumb,
+ NBreadcrumbItem,
+ NSteps,
+ NStep,
+ NButton,
+ NText,
+ NIcon,
+ NCard,
+ useDialog
+} from 'naive-ui'
+import StepOneForm from './StepOneForm'
+import StepTwoForm from './StepTwoForm'
+import StepTwoTable from './StepTwoTable'
+import StepThreeParams from './StepThreeParams'
+import { PlusOutlined } from '@vicons/antd'
+import { useRoute, useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+import { useDetail } from './use-detail'
+import styles from './index.module.scss'
+
+const VirtualTablesDetail = defineComponent({
+ name: 'VirtualTablesDetail',
+ setup() {
+ const { t } = useI18n()
+ const route = useRoute()
+ const router = useRouter()
+ const dialog = useDialog()
+ const {
+ state,
+ stepOneFormRef,
+ stepTwoFormRef,
+ onAddRecord,
+ onChangeStep,
+ createOrUpdate
+ } = useDetail(route.params.id as string)
+
+ const onClose = () => {
+ dialog.warning({
+ title: t('virtual_tables.warning'),
+ content: t('virtual_tables.close_confirm_tips'),
+ onPositiveClick: () => {
+ router.push({
+ name: 'datasource-list',
+ query: { tab: 'virtual-tables' }
+ })
+ },
+ positiveText: t('virtual_tables.confirm'),
+ negativeText: t('virtual_tables.cancel')
+ })
+ }
+
+ return () => (
+ <NSpace vertical>
+ <NBreadcrumb>
+ <NBreadcrumbItem
+ // @ts-ignore
+ onClick={onClose}
+ >
+ {t('virtual_tables.virtual_tables')}
+ </NBreadcrumbItem>
+ <NBreadcrumbItem>
+ {t(
+ route.params.id
+ ? 'virtualTables.edit_virtual_tables'
+ : 'virtualTables.create_virtual_tables'
+ )}
+ </NBreadcrumbItem>
+ </NBreadcrumb>
+ <NCard
+ title={t(
+ route.params.id
+ ? 'virtualTables.edit_virtual_tables'
+ : 'virtualTables.create_virtual_tables'
+ )}
+ >
+ <div class={styles['detail-content']}>
+ <NSteps current={state.current} class={styles['detail-step']}>
+ <NStep title={t('virtual_tables.configure')} />
+ <NStep title={t('virtual_tables.model')} />
+ <NStep title={t('virtual_tables.complete')} />
+ </NSteps>
+ <div class={styles['width-100']} v-show={state.current === 1}>
+ <NSpace justify='center'>
+ <StepOneForm params={state.stepOne} ref={stepOneFormRef} />
+ </NSpace>
+ </div>
+ <div class={styles['detail-step-two']} v-show={state.current ===
2}>
+ <StepTwoForm ref={stepTwoFormRef} />
+ <div class={styles['detail-table-header']}>
+ <NText class={styles['detail-table-title']}>
+ {t('virtual_tables.table_structure')}
+ </NText>
+ <NButton text type='primary' onClick={onAddRecord}>
+ {{
+ icon: () => (
+ <NIcon>
+ <PlusOutlined />
+ </NIcon>
+ ),
+ default: () => t('virtual_tables.add')
+ }}
+ </NButton>
+ </div>
+ <StepTwoTable
+ //list={state.stepTwo.list}
+ fieldTypes={state.fieldTypes}
+ />
+ </div>
+ <div
+ class={styles['detail-step-three']}
+ v-show={state.current === 3}
+ >
+ <div class={styles['detail-step-three-params']}>
+ <StepThreeParams
+ class={styles['detail-step-three-left']}
+ params={[
+ {
+ label: t('virtual_tables.source_type'),
+ value: state.stepOne.pluginName || ''
+ },
+ {
+ label: t('virtual_tables.source_name'),
+ value: state.stepOne.datasourceName || ''
+ },
+ {
+ label: t('virtual_tables.virtual_tables_name'),
+ value: state.stepOne.tableName || ''
+ }
+ ]}
+ />
+ <StepThreeParams
+ class={styles['detail-step-three-right']}
+ params={state.stepTwo.config}
+ cols={3}
+ />
+ </div>
+ <StepTwoTable
+ class={styles['width-100']}
+ //list={state.stepTwo.list}
+ plain
+ fieldTypes={state.fieldTypes}
+ />
+ </div>
+ </div>
+ <NSpace justify='end'>
+ <NButton
+ v-show={state.current !== 1}
+ type='primary'
+ onClick={() => void onChangeStep(-1)}
+ >
+ {t('virtual_tables.previous_step')}
+ </NButton>
+ <NButton onClick={onClose}>{t('virtual_tables.cancel')}</NButton>
+
+ {state.current !== 3 && (
+ <NButton
+ type='primary'
+ onClick={() => void onChangeStep(1)}
+ loading={state.goNexting}
+ >
+ {t('virtual_tables.next_step')}
+ </NButton>
+ )}
+ <NButton
+ v-show={state.current === 3}
+ onClick={createOrUpdate}
+ loading={state.saving}
+ type='primary'
+ >
+ {t('virtual_tables.confirm')}
+ </NButton>
+ </NSpace>
+ </NCard>
+ </NSpace>
+ )
+ }
+})
+
+export default VirtualTablesDetail
diff --git a/seatunnel-ui/src/views/virtual-tables/index.module.scss
b/seatunnel-ui/src/views/virtual-tables/index.module.scss
new file mode 100644
index 00000000..4139b9d7
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/index.module.scss
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+.type-width {
+ width: 220px;
+}
+.width-100 {
+ width: 100%;
+}
+.detail-step {
+ width: 50vw;
+ margin-top: 20px;
+ margin-left: 16vw;
+ margin-bottom: 30px;
+}
+.detail-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+.detail-step-two {
+ width: 100%;
+ padding-bottom: 20px;
+ padding-top: 10px;
+}
+.detail-step-three {
+ width: 100%;
+ padding-bottom: 20px;
+}
+.detail-table-header {
+ height: 30px;
+ display: flex;
+ justify-content: space-between;
+}
+.detail-table-title {
+ font-weight: bold;
+}
+.step-two-table {
+ :global {
+ .n-form-item-feedback-wrapper {
+ line-height: 14px;
+ min-height: 14px;
+ }
+ }
+}
+.table-cell-center {
+ text-align: center !important;
+}
+.edit-row {
+ :global {
+ td {
+ padding-bottom: 0px;
+ }
+ }
+}
+.detail-step-three-params {
+ display: flex;
+ margin-bottom: 10px;
+ justify-content: space-between;
+}
+.detail-step-three-left {
+ width: 33%;
+ margin-right: 10px;
+}
+.detail-step-three-right {
+ flex-grow: 1;
+}
diff --git a/seatunnel-ui/src/views/virtual-tables/list/index.tsx
b/seatunnel-ui/src/views/virtual-tables/list/index.tsx
new file mode 100644
index 00000000..03bfdea1
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/list/index.tsx
@@ -0,0 +1,120 @@
+/*
+ * 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 } from 'vue'
+import {
+ NButton,
+ NInput,
+ NSelect,
+ NIcon,
+ NSpace,
+ NDataTable,
+ NPagination,
+ NCard,
+ SelectOption,
+ SelectGroupOption
+} from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
+import { useTable } from './use-table'
+import { useColumns } from './use-columns'
+//import { useSource } from '../datasource/list/use-source'
+import styles from '../index.module.scss'
+
+const VirtualTablesList = defineComponent({
+ setup() {
+ const { t } = useI18n()
+ const router = useRouter()
+ //const { state: sourceState } = useSource(true)
+ const { columns } = useColumns(
+ (id: string, type: 'edit' | 'delete') => {
+ if (type === 'edit') {
+ router.push({ name: 'virtual-tables-editor', params: { id: id } })
+ } else {
+ onDelete(id)
+ }
+ }
+ )
+ const {
+ state,
+ onSearch,
+ onDelete,
+ onPageChange,
+ onPageSizeChange
+ } = useTable()
+
+ return () => (
+ <NSpace vertical>
+ <NCard title={t('virtual_tables.virtual_tables')}>
+ {{
+ 'header-extra': () => <NSpace>
+ <NSelect
+ v-model:value={state.params.pluginName}
+ clearable
+ placeholder={t('virtual_tables.source_type_tips')}
+ //options={
+ // sourceState.types as Array<SelectGroupOption |
SelectOption>
+ //}
+ class={styles['type-width']}
+ />
+ <NInput
+ v-model:value={state.params.datasourceName}
+ clearable
+ placeholder={t('virtual_tables.source_name_tips')}
+ />
+ <NButton type='primary' onClick={onSearch}>
+ {t('virtual_tables.search')}
+ </NButton>
+ <NButton
+ onClick={() => {
+ router.push({ name: 'virtual-tables-create' })
+ }}
+ type='success'
+ >
+ {t('virtual_tables.create')}
+ </NButton>
+ </NSpace>
+ }}
+ </NCard>
+ <NCard>
+ <NSpace vertical>
+ <NDataTable
+ columns={columns.value}
+ data={state.list}
+ loading={state.loading}
+ striped
+ />
+ <NSpace justify='center'>
+ <NPagination
+ v-model:page={state.page}
+ v-model:page-size={state.pageSize}
+ item-count={state.itemCount}
+ show-size-picker
+ page-sizes={[10, 30, 50]}
+ show-quick-jumper
+ on-update:page={onPageChange}
+ on-update:page-size={onPageSizeChange}
+ />
+ </NSpace>
+ </NSpace>
+ </NCard>
+ </NSpace>
+ )
+ }
+})
+
+export default VirtualTablesList
diff --git a/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts
b/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts
new file mode 100644
index 00000000..860dd000
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts
@@ -0,0 +1,115 @@
+/*
+ * 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 { h, ref, watch, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { EditOutlined } from '@vicons/antd'
+import { NButton, NSpace } from 'naive-ui'
+//import type { TableColumns, VirtualTableRecord } from '../types'
+
+export function useColumns(onCallback: Function) {
+ const { t } = useI18n()
+ const columns = ref()
+ const getColumns = () => {
+ const columns = [
+ {
+ title: 'ID',
+ key: 'id',
+ render: (ignore: any, index: number) => index + 1
+ },
+ {
+ title: t('virtual_tables.table_name'),
+ key: 'tableName',
+ align: 'left'
+ },
+ {
+ title: t('virtual_tables.database_name'),
+ key: 'databaseName',
+ align: 'left'
+ },
+ {
+ title: t('virtual_tables.source_name'),
+ key: 'datasourceName',
+ align: 'left'
+ },
+ {
+ title: t('virtual_tables.source_type'),
+ key: 'pluginName'
+ },
+ {
+ title: t('virtual_tables.creator'),
+ key: 'createUserName'
+ },
+ {
+ title: t('virtual_tables.creation_time'),
+ key: 'createTime'
+ //render: (rowData: VirtualTableRecord) =>
+ // renderTableTime(rowData.createTime)
+ },
+ {
+ title: t('virtual_tables.updater'),
+ key: 'updateUserName'
+ },
+ {
+ title: t('virtual_tables.update_time'),
+ key: 'updateTime'
+ //render: (rowData: VirtualTableRecord) =>
+ // renderTableTime(rowData.createTime)
+ },
+ {
+ title: t('virtual_tables.operation'),
+ key: 'operation',
+ render: (row: any) =>
+ h(NSpace, null, {
+ default: () => [
+ h(
+ NButton,
+ {
+ text: true,
+ onClick: () => void onCallback(row.tableId, 'edit')
+ },
+ {
+ default: () => t('virtual_tables.edit')
+ }
+ ),
+ h(
+ NButton,
+ {
+ text: true,
+ onClick: () => void onCallback(row.tableId, 'delete')
+ },
+ { default: () => t('virtual_tables.delete') }
+ )
+ ]
+ })
+ }
+ ]
+ return columns
+ }
+
+ watch(useI18n().locale, () => {
+ columns.value = getColumns()
+ })
+
+ onMounted(() => {
+ columns.value = getColumns()
+ })
+
+ return {
+ columns
+ }
+}
diff --git a/seatunnel-ui/src/views/virtual-tables/list/use-table.ts
b/seatunnel-ui/src/views/virtual-tables/list/use-table.ts
new file mode 100644
index 00000000..a75d9294
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/list/use-table.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 { onMounted, reactive } from 'vue'
+import {
+ virtualTableList
+ //deleteVirtualTable
+} from '@/service/virtual-tables'
+import { useRoute, useRouter } from 'vue-router'
+//import type { Params } from '../types'
+
+export function useTable() {
+ const initialParams: any = {
+ pluginName: null,
+ datasourceName: null
+ }
+ const state = reactive({
+ params: { ...initialParams },
+ list: [],
+ loading: false,
+ page: 1,
+ pageSize: 10,
+ itemCount: 0
+ })
+ const route = useRoute()
+ const router = useRouter()
+
+ const getList = async () => {
+ const result = await virtualTableList({
+ pageNo: state.page,
+ pageSize: state.pageSize,
+ ...state.params
+ })
+ console.log(result)
+ state.list = result?.data
+ state.itemCount = result?.total
+ }
+
+ const updateList = () => {
+ if (state.list.length === 1 && state.page > 1) {
+ --state.page
+ }
+ getList()
+ }
+
+ const onDelete = async (id: string) => {
+ //await deleteVirtualTable(id)
+ updateList()
+ }
+
+ const initSearch = () => {
+ const { pluginName, datasourceName } = route.query
+ if (pluginName) {
+ state.params.pluginName = pluginName as string
+ if (datasourceName) {
+ state.params.datasourceName = datasourceName as string
+ }
+ }
+ }
+
+ const onSearch = () => {
+ const query = (
+ state.params.pluginName ? { pluginName: state.params.pluginName } : null
+ ) as any
+
+ if (state.params.datasourceName) {
+ query.datasourceName = state.params.datasourceName
+ }
+
+ if (query) {
+ router.replace({ query: { tab: route.query.tab, ...query } })
+ }
+
+ state.page = 1
+ getList()
+ }
+
+ const onPageChange = (page: number) => {
+ state.page = page
+ getList()
+ }
+
+ const onPageSizeChange = (pageSize: number) => {
+ state.page = 1
+ state.pageSize = pageSize
+ getList()
+ }
+
+ onMounted(() => {
+ initSearch()
+ onSearch()
+ })
+
+ return {
+ state,
+ onSearch,
+ onDelete,
+ onPageChange,
+ onPageSizeChange
+ }
+}
diff --git a/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx
b/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx
new file mode 100644
index 00000000..632a32d5
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx
@@ -0,0 +1,144 @@
+/*
+ * 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, ref, toRef } from 'vue'
+import {
+ NForm,
+ NFormItem,
+ NSelect,
+ NInput,
+ SelectOption,
+ SelectGroupOption
+} from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+//import { useSource } from '../datasource/list/use-source'
+import { useTable } from '../datasource/list/use-table'
+import styles from './index.module.scss'
+
+const StepOneForm = defineComponent({
+ name: 'StepOneForm',
+ props: {
+ params: {
+ type: Object,
+ default: {}
+ }
+ },
+ setup(props, { expose }) {
+ const { t } = useI18n()
+ //const { state: sourceState } = useSource(true)
+ const { data: datasourceState, getList } = useTable()
+ const rules = {
+ pluginName: {
+ required: true,
+ trigger: ['input', 'blur'],
+ message: t('virtual_tables.source_type_tips')
+ },
+ datasourceName: {
+ required: true,
+ trigger: ['input', 'blur'],
+ message: t('virtual_tables.source_name_tips')
+ },
+ tableName: {
+ required: true,
+ trigger: ['input', 'blur'],
+ message: t('virtual_tables.virtual_tables_name_tips')
+ }
+ }
+ const paramsRef = toRef(props, 'params')
+ const stepOneFormRef = ref()
+
+ const handleUpdateType = (type: string) => {
+ if (type === paramsRef.value.pluginName) return
+ datasourceState.pageSize = 99999
+ //getList(type)
+ paramsRef.value.datasourceName = null
+ paramsRef.value.tableName = null
+ }
+
+ expose({
+ validate: async () => {
+ await stepOneFormRef.value.validate()
+ }
+ })
+
+ return () => (
+ <NForm
+ rules={rules}
+ ref={stepOneFormRef}
+ require-mark-placement='left'
+ label-align='right'
+ labelPlacement='left'
+ model={paramsRef.value}
+ labelWidth={100}
+ >
+ <NFormItem
+ label={t('virtual_tables.source_type')}
+ path='pluginName'
+ show-require-mark
+ >
+ <NSelect
+ v-model:value={props.params.pluginName}
+ filterable
+ placeholder={t('virtual_tables.source_type_tips')}
+ //options={
+ // sourceState.types as Array<SelectGroupOption | SelectOption>
+ //}
+ //loading={sourceState.loading}
+ class={styles['type-width']}
+ onUpdateValue={(value) => void handleUpdateType(value)}
+ />
+ </NFormItem>
+ <NFormItem
+ label={t('virtual_tables.source_name')}
+ path='datasourceName'
+ show-require-mark
+ >
+ <NSelect
+ v-model:value={paramsRef.value.datasourceName}
+ filterable
+ placeholder={t('virtual_tables.source_name_tips')}
+ options={datasourceState.list.map(
+ (item: { datasourceName: string; id: string }) => ({
+ label: item.datasourceName,
+ value: item.datasourceName,
+ id: item.id
+ })
+ )}
+ //loading={datasourceState.loading}
+ class={styles['type-width']}
+ onUpdateValue={(value, option: { id: string }) => {
+ paramsRef.value.datasourceId = option.id
+ }}
+ />
+ </NFormItem>
+ <NFormItem
+ label={t('virtual_tables.virtual_tables_name')}
+ path='tableName'
+ show-require-mark
+ >
+ <NInput
+ v-model:value={paramsRef.value.tableName}
+ clearable
+ placeholder={t('virtual_tables.virtual_tables_name_tips')}
+ class={styles['type-width']}
+ />
+ </NFormItem>
+ </NForm>
+ )
+ }
+})
+
+export default StepOneForm
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts
b/seatunnel-ui/src/views/virtual-tables/step-three-params.tsx
similarity index 52%
copy from seatunnel-ui/src/locales/zh_CN/index.ts
copy to seatunnel-ui/src/views/virtual-tables/step-three-params.tsx
index c3e11f4a..92ee2b9c 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/views/virtual-tables/step-three-params.tsx
@@ -15,26 +15,37 @@
* limitations under the License.
*/
-import login from '@/locales/zh_CN/login'
-import menu from '@/locales/zh_CN/menu'
-import modal from '@/locales/zh_CN/modal'
-import user_manage from '@/locales/zh_CN/user-manage'
-import data_pipes from '@/locales/zh_CN/data-pipes'
-import log from '@/locales/zh_CN/log'
-import jobs from '@/locales/zh_CN/jobs'
-import tasks from '@/locales/zh_CN/tasks'
-import setting from '@/locales/zh_CN/setting'
-import datasource from '@/locales/zh_CN/datasource'
+import { defineComponent, PropType } from 'vue'
+import { NCard, NGrid, NGi, NSpace } from 'naive-ui'
-export default {
- login,
- menu,
- modal,
- user_manage,
- data_pipes,
- log,
- jobs,
- tasks,
- setting,
- datasource
-}
+const StepThreeParams = defineComponent({
+ name: 'StepThreeParams',
+ props: {
+ params: {
+ type: Array as PropType<{ label: string; value: string }[]>,
+ default: []
+ },
+ cols: {
+ type: Number,
+ default: 1
+ }
+ },
+ setup(props) {
+ return () => (
+ <NCard>
+ <NGrid cols={props.cols}>
+ {props.params.map((item) => (
+ <NGi>
+ <NSpace>
+ <span>{item.label}:</span>
+ <span>{item.value}</span>
+ </NSpace>
+ </NGi>
+ ))}
+ </NGrid>
+ </NCard>
+ )
+ }
+})
+
+export default StepThreeParams
diff --git a/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx
b/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx
new file mode 100644
index 00000000..a14793dd
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx
@@ -0,0 +1,117 @@
+/*
+ * 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, reactive, ref } from 'vue'
+import { NForm } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { DynamicFormItem } from '@/components/dynamic-form/dynamic-form-item'
+//import { StructureItem } from '@/store/datasource/form-structures'
+//import { getDynamicConfig } from '@/service/modules/virtual-table'
+import { useFormField } from '@/components/dynamic-form/use-form-field'
+import { useFormRequest } from '@/components/dynamic-form/use-form-request'
+import { useFormValidate } from '@/components/dynamic-form/use-form-validate'
+import { useFormStructure } from '@/components/dynamic-form/use-form-structure'
+
+const StepTwoForm = defineComponent({
+ name: 'StepTwoForm',
+ setup(props, { expose }) {
+ const { t } = useI18n()
+ const stepTwoFormRef = ref()
+
+ const state = reactive({
+ rules: {},
+ //formStructure: [] as StructureItem[],
+ locales: {} as any,
+ formName: 'step-two-form',
+ detailForm: {} as { [key: string]: string },
+ config: [] as { key: string; value: string; label: string }[]
+ })
+
+ const getFormItems = async (pluginName: string, datasourceName: string) =>
{
+ if (!pluginName || !datasourceName) return false
+ //const result = await getDynamicConfig({
+ // pluginName,
+ // datasourceName
+ //})
+ try {
+ //const res = JSON.parse(result)
+ //
+ //state.locales = res.locales
+ //Object.assign(state.detailForm, useFormField(res.forms))
+ //Object.assign(
+ // state.rules,
+ // useFormValidate(res.forms, state.detailForm, t)
+ //)
+ //state.formStructure = useFormStructure(
+ // res.apis ? useFormRequest(res.apis, res.forms) : res.forms
+ //) as any
+ //
+ //state.formStructure = res.forms.map((item: any) => ({
+ // ...item,
+ // span: 8
+ //}))
+ return true
+ } catch (err) {
+ return false
+ }
+ }
+
+ const getValues = async () => {
+ await stepTwoFormRef.value.validate()
+ //return state.formStructure.map((item) => {
+ // return {
+ // label: item.label,
+ // key: item.field,
+ // value: state.detailForm[item.field]
+ // }
+ //})
+ }
+
+ const setValues = (values: { [key: string]: string }) => {
+ Object.assign(state.detailForm, values)
+ }
+
+ expose({
+ validate: async () => {
+ await stepTwoFormRef.value.validate()
+ },
+ getFormItems,
+ getValues,
+ setValues
+ })
+
+ return () => (
+ <NForm
+ rules={state.rules}
+ ref={stepTwoFormRef}
+ require-mark-placement='left'
+ model={state.detailForm}
+ labelWidth={100}
+ >
+ {/*{state.formStructure.length > 0 && (*/}
+ {/* <DynamicFormItem*/}
+ {/* model={state.detailForm}*/}
+ {/* formStructure={state.formStructure}*/}
+ {/* name={state.formName}*/}
+ {/* locales={state.locales}*/}
+ {/* />*/}
+ {/*)}*/}
+ </NForm>
+ )
+ }
+})
+
+export default StepTwoForm
diff --git a/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx
b/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx
new file mode 100644
index 00000000..c90e85e3
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx
@@ -0,0 +1,327 @@
+/*
+ * 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, PropType, toRef, ref, onMounted } from 'vue'
+import {
+ NTable,
+ NText,
+ NTooltip,
+ NFormItem,
+ NInput,
+ NSelect,
+ NSpace,
+ NButton,
+ NPopconfirm,
+ NIcon,
+ NEmpty
+} from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { EditOutlined, DeleteOutlined } from '@vicons/antd'
+import styles from './index.module.scss'
+//import type { IDetailTableRecord } from './types'
+
+const EditRow = defineComponent({
+ name: 'EditRow',
+ props: {
+ row: {
+ type: Object as PropType<any>,
+ default: {}
+ },
+ plain: {
+ type: Boolean,
+ default: false
+ },
+ fieldTypes: {
+ type: Array as PropType<string[]>,
+ default: []
+ }
+ },
+ emits: ['updateValue', 'delete'],
+ setup(props, { emit }) {
+ const { t } = useI18n()
+ const inputRef = ref()
+ const fieldTypeRef = ref()
+ const onUpdateValue = (field: keyof any, value: any) => {
+ emit('updateValue', field, value)
+ }
+ onMounted(() => {
+ inputRef.value.focus()
+ })
+ return () => (
+ <tr>
+ <td>
+ <NFormItem
+ showLabel={false}
+ feedback={
+ props.row.fieldName ? '' : t('virtual_tables.field_name_tips')
+ }
+ validation-status={props.row.fieldName ? '' : 'error'}
+ >
+ <NInput
+ autofocus
+ value={props.row.fieldName}
+ clearable
+ onUpdateValue={(value) => void onUpdateValue('fieldName', value)}
+ ref={inputRef}
+ />
+ </NFormItem>
+ </td>
+ <td>
+ <NFormItem showLabel={false} v-show={props.row.isEdit}>
+ <NSelect
+ ref={fieldTypeRef}
+ value={props.row.fieldType}
+ options={props.fieldTypes.map((item) => ({
+ label: item,
+ value: item
+ }))}
+ filterable
+ onUpdateValue={(value) => void onUpdateValue('fieldType', value)}
+ />
+ </NFormItem>
+ </td>
+ <td>
+ <NFormItem showLabel={false}>
+ <NSelect
+ value={props.row.nullable as number}
+ options={[
+ { value: 1, label: t('virtual_tables.yes') },
+ { value: 0, label: t('virtual_tables.no') }
+ ]}
+ onUpdateValue={(value) => void onUpdateValue('nullable', value)}
+ />
+ </NFormItem>
+ </td>
+ <td>
+ <NFormItem showLabel={false}>
+ <NSelect
+ value={props.row.primaryKey as number}
+ options={[
+ { value: 1, label: t('virtual_tables.yes') },
+ { value: 0, label: t('virtual_tables.no') }
+ ]}
+ onUpdateValue={(value) => void onUpdateValue('primaryKey',
value)}
+ />
+ </NFormItem>
+ </td>
+ <td>
+ <NFormItem showLabel={false}>
+ <NInput
+ value={props.row.fieldComment}
+ clearable
+ onUpdateValue={(value) =>
+ void onUpdateValue('fieldComment', value)
+ }
+ />
+ </NFormItem>
+ </td>
+ <td>
+ <NFormItem showLabel={false}>
+ <NInput
+ value={props.row.defaultValue}
+ clearable
+ onUpdateValue={(value) =>
+ void onUpdateValue('defaultValue', value)
+ }
+ />
+ </NFormItem>
+ </td>
+ {!props.plain && (
+ <td>
+ <NFormItem showLabel={false}>
+ <NSpace align='start'>
+ <NButton
+ size='small'
+ onClick={() => void onUpdateValue('isEdit', false)}
+ >
+ {t('virtual_tables.cancel')}
+ </NButton>
+ <NButton
+ type='primary'
+ size='small'
+ onClick={() => {
+ if (!props.row.fieldName) {
+ inputRef.value.focus()
+ return
+ }
+ if (!props.row.fieldType) {
+ fieldTypeRef.value.focus()
+ return
+ }
+ onUpdateValue('isEdit', false)
+ }}
+ >
+ {t('virtual_tables.confirm')}
+ </NButton>
+ </NSpace>
+ </NFormItem>
+ </td>
+ )}
+ </tr>
+ )
+ }
+})
+
+const StepTwoTable = defineComponent({
+ name: 'StepTwoTable',
+ props: {
+ list: {
+ type: Array as PropType<any[]>,
+ default: []
+ },
+ plain: {
+ type: Boolean,
+ default: false
+ },
+ fieldTypes: {
+ type: Array as PropType<string[]>,
+ default: []
+ }
+ },
+ setup(props) {
+ const { t } = useI18n()
+ const listRef = toRef(props, 'list')
+ return () => (
+ <NTable striped class={styles['step-two-table']}>
+ <thead>
+ <th>
+ <NText type='error'>*</NText>
+ {t('virtual_tables.field_name')}
+ </th>
+ <th class={styles['table-cell-center']}>
+ <NText type='error'>*</NText>
+ {t('virtual_tables.field_type')}
+ </th>
+ <th class={styles['table-cell-center']}>
+ <NText type='error'>*</NText>
+ {t('virtual_tables.is_null')}
+ </th>
+ <th class={styles['table-cell-center']}>
+ <NText type='error'>*</NText>
+ {t('virtual_tables.is_primary_key')}
+ </th>
+ <th>{t('virtual_tables.description')}</th>
+ <th>{t('virtual_tables.default_value')}</th>
+ {!props.plain && <th>{t('virtual_tables.operation')}</th>}
+ </thead>
+ <tbody>
+ {listRef.value.map((row, index) =>
+ row.isEdit && !props.plain ? (
+ <EditRow
+ key={row.key}
+ row={row}
+ plain={props.plain}
+ fieldTypes={props.fieldTypes}
+ onUpdateValue={(
+ field: keyof any,
+ value: any
+ ) => {
+ // @ts-ignore
+ listRef.value[index][field] = value
+ }}
+ class={styles[row.isEdit ? 'edit-row' : 'plain-row']}
+ />
+ ) : (
+ <tr>
+ <td>
+ <span>{row.fieldName}</span>
+ </td>
+ <td class={styles['table-cell-center']}>
+ <span>{row.fieldType}</span>
+ </td>
+ <td class={styles['table-cell-center']}>
+ <span>
+ {row.nullable
+ ? t('virtual_tables.yes')
+ : t('virtual_tables.no')}
+ </span>
+ </td>
+ <td class={styles['table-cell-center']}>
+ <span>
+ {row.primaryKey
+ ? t('virtual_tables.yes')
+ : t('virtual_tables.no')}
+ </span>
+ </td>
+ <td>
+ <span>{row.fieldComment}</span>
+ </td>
+ <td>
+ <span>{row.defaultValue}</span>
+ </td>
+ {!props.plain && (
+ <td>
+ <NSpace align='start'>
+ <NTooltip>
+ {{
+ trigger: () => (
+ <NButton
+ type='primary'
+ circle
+ size='small'
+ onClick={() => {
+ listRef.value[index]['isEdit'] = true
+ }}
+ >
+ <NIcon>
+ <EditOutlined />
+ </NIcon>
+ </NButton>
+ ),
+ default: () => t('virtual_tables.edit')
+ }}
+ </NTooltip>
+ <NTooltip>
+ {{
+ trigger: () => (
+ <NPopconfirm
+ onPositiveClick={() => {
+ listRef.value.splice(index, 1)
+ }}
+ >
+ {{
+ trigger: () => (
+ <NButton type='error' circle size='small'>
+ <NIcon>
+ <DeleteOutlined />
+ </NIcon>
+ </NButton>
+ ),
+ default: () =>
t('virtual_tables.delete_confirm')
+ }}
+ </NPopconfirm>
+ ),
+ default: () => t('virtual_tables.delete')
+ }}
+ </NTooltip>
+ </NSpace>
+ </td>
+ )}
+ </tr>
+ )
+ )}
+ <tr v-show={!listRef.value.length}>
+ <td colspan={6}>
+ <NEmpty />
+ </td>
+ </tr>
+ </tbody>
+ </NTable>
+ )
+ }
+})
+
+export default StepTwoTable
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts
b/seatunnel-ui/src/views/virtual-tables/types.ts
similarity index 65%
copy from seatunnel-ui/src/locales/zh_CN/menu.ts
copy to seatunnel-ui/src/views/virtual-tables/types.ts
index 5270249f..09cee8c8 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/views/virtual-tables/types.ts
@@ -14,14 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+export type { TableColumns } from 'naive-ui/es/data-table/src/interface'
+export type { DataTableColumns } from 'naive-ui'
+//export type {
+// VirtualTableDetail,
+// VirtualTableRecord,
+// IDetailTableRecord
+//} from '@/service/modules/virtual-table/types'
+//import type { VirtualTableListParameters } from
'@/service/modules/virtual-table/types'
-export default {
- data_pipes: '数据管道',
- jobs: '工作',
- user_manage: '用户管理',
- help: '帮助',
- setting: '设置',
- logout: '登出',
- tasks: '任务',
- datasource: '数据源'
-}
+//export type Params = Omit<VirtualTableListParameters, 'pageNo' | 'pageSize'>
diff --git a/seatunnel-ui/src/views/virtual-tables/use-detail.ts
b/seatunnel-ui/src/views/virtual-tables/use-detail.ts
new file mode 100644
index 00000000..0c2f709b
--- /dev/null
+++ b/seatunnel-ui/src/views/virtual-tables/use-detail.ts
@@ -0,0 +1,184 @@
+/*
+ * 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, ref, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+//import {
+// getVirtualTableDetail,
+// createVirtualTable,
+// updateVirtualTable,
+// getFieldType
+//} from '@/service/modules/virtual-table'
+import { omit } from 'lodash'
+import { useRouter } from 'vue-router'
+//import type { IDetailTableRecord, VirtualTableDetail } from './types'
+
+export const useDetail = (id: string) => {
+ const state = reactive({
+ current: 1,
+ loading: false,
+ saving: false,
+ stepOne: {
+ pluginName: null,
+ datasourceName: null,
+ tableName: '',
+ datasourceId: ''
+ },
+ stepTwo: {
+ //list: [] as IDetailTableRecord[],
+ loading: false,
+ config: []
+ },
+ fieldTypes: [] as string[],
+ goNexting: false
+ })
+ const { t } = useI18n()
+ let tempDatabaseProperties: any
+ const router = useRouter()
+ const defaultRecord = {
+ fieldName: '',
+ fieldType: '',
+ nullable: 0,
+ primaryKey: 0,
+ isEdit: true
+ }
+ const stepOneFormRef = ref()
+ const stepTwoFormRef = ref()
+
+ const queryById = async () => {
+ if (state.loading) return {}
+ state.loading = true
+ //const res = await getVirtualTableDetail(id)
+ //state.stepOne.pluginName = res.pluginName
+ //state.stepOne.datasourceName = res.datasourceName
+ //state.stepOne.datasourceId = res.datasourceId
+ //state.stepOne.tableName = res.tableName
+ //state.stepTwo.list = res.fields.map((item: { [key: string]: any }) => ({
+ // ...item,
+ // nullable: Number(item.nullable),
+ // primaryKey: Number(item.primaryKey)
+ //}))
+ //tempDatabaseProperties = res.datasourceProperties
+ state.loading = false
+ }
+
+ const queryFieldsType = async () => {
+ //const res = await getFieldType()
+ //state.fieldTypes = res
+ //defaultRecord.fieldType = state.fieldTypes[0]
+ }
+
+ const formatParams = () => {
+ const databaseProperties = {} as { [key: string]: string }
+ state.stepTwo.config.forEach((item: { key: string; value: string }) => {
+ databaseProperties[item.key] = item.value
+ })
+ return {
+ datasourceId: state.stepOne.datasourceId,
+ datasourceName: state.stepOne.datasourceName || '',
+ pluginName: state.stepOne.pluginName || '',
+ tableName: state.stepOne.tableName,
+ //tableFields: state.stepTwo.list.map((item) => ({
+ // ...omit(item, ['key', 'isEdit']),
+ // nullable: Boolean(item.nullable),
+ // primaryKey: Boolean(item.nullable)
+ //})),
+ databaseProperties,
+ databaseName: 'default'
+ }
+ }
+
+ const createOrUpdate = async () => {
+ const values = formatParams()
+ if (state.saving) return false
+ state.saving = true
+
+ try {
+ //id
+ // ? await updateVirtualTable(values, id)
+ // : await createVirtualTable(values)
+
+ state.saving = false
+ router.push({
+ name: 'datasource-list',
+ query: { tab: 'virtual-tables' }
+ })
+ return true
+ } catch (err) {
+ state.saving = false
+ return false
+ }
+ }
+
+ const onAddRecord = () => {
+ //state.stepTwo.list.unshift({
+ // ...defaultRecord,
+ // key: Date.now() + Math.random() * 1000
+ //})
+ }
+
+ const onChangeStep = async (step: -1 | 1) => {
+ if (state.current === 1 && step === 1) {
+ state.goNexting = true
+ try {
+ await stepOneFormRef.value.validate()
+ await stepTwoFormRef.value.getFormItems(
+ state.stepOne.pluginName,
+ state.stepOne.datasourceName
+ )
+ if (tempDatabaseProperties)
+ stepTwoFormRef.value.setValues(tempDatabaseProperties)
+ } finally {
+ state.goNexting = false
+ }
+ }
+ if (state.current === 2 && step === 1) {
+ state.goNexting = true
+ try {
+ const values = await stepTwoFormRef.value.getValues()
+ state.stepTwo.config = values
+ //const flag = state.stepTwo.list.some((item) => item.isEdit)
+ //if (flag) {
+ // window.$message.error(t('virtual_tables.save_data_tips'))
+ // return
+ //}
+ //if (state.stepTwo.list.length === 0) {
+ // window.$message.error(t('virtual_tables.table_data_required_tips'))
+ // return
+ //}
+ } finally {
+ state.goNexting = false
+ }
+ }
+ state.current += step
+ }
+
+ onMounted(() => {
+ if (id) {
+ queryById()
+ }
+ queryFieldsType()
+ })
+
+ return {
+ state,
+ stepOneFormRef,
+ stepTwoFormRef,
+ createOrUpdate,
+ onAddRecord,
+ onChangeStep
+ }
+}