From ec56dd7ce94a4265569b0db9cf0693a41d2d83ed Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 09:42:33 +0800 Subject: [PATCH 01/10] refactor: enhance license check logic in Header.vue --- apps/daas/src/layouts/Header.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/daas/src/layouts/Header.vue b/apps/daas/src/layouts/Header.vue index d221d4dd72..acb9d57614 100644 --- a/apps/daas/src/layouts/Header.vue +++ b/apps/daas/src/layouts/Header.vue @@ -227,7 +227,8 @@ onMounted(() => { if ( import.meta.env.VUE_APP_MODE !== 'community' && - window.getSettingByKey?.('SHOW_LICENSE') + window.getSettingByKey?.('SHOW_LICENSE') && + window.getSettingByKey('checkLicense') !== 'false' ) { getLicense() } From 0c68bf861df9682e5a249c4df8c6c2b317ec110b Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 10:02:33 +0800 Subject: [PATCH 02/10] refactor: enhance NodeLog and Alert components for improved usability - Updated NodeLog.vue to replace span with el-button for better accessibility and styling. - Modified Alert.vue to allow empty string as a valid option in SelectList components and added clearable functionality for improved user experience. - Cleaned up button attributes for consistency in styling. --- packages/business/src/components/logs/NodeLog.vue | 8 +++++--- .../src/components/monitor/components/Alert.vue | 14 ++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/business/src/components/logs/NodeLog.vue b/packages/business/src/components/logs/NodeLog.vue index 9db9c40586..066eecb9db 100644 --- a/packages/business/src/components/logs/NodeLog.vue +++ b/packages/business/src/components/logs/NodeLog.vue @@ -1049,8 +1049,10 @@ Stack Trace: ${this.codeDialog.data.errorStack ? `\n${this.codeDialog.data.error }} - {{ fullscreen ? 'suoxiao' : 'fangda' }} @@ -1059,7 +1061,7 @@ Stack Trace: ${this.codeDialog.data.errorStack ? `\n${this.codeDialog.data.error ? $t('packages_form_js_editor_exit_fullscreen') : $t('packages_form_js_editor_fullscreen') }} - +
@@ -274,15 +276,15 @@ export default {
{{ $t('packages_dag_monitor_bottompanel_rizhi') }} {{ $t('public_button_close') }} Date: Mon, 12 May 2025 11:33:48 +0800 Subject: [PATCH 03/10] style: update BottomPanel and Record components for improved layout and accessibility - Added a new class to BottomPanel for better styling and z-index management. - Replaced span with el-button in BottomPanel for enhanced accessibility. - Adjusted positioning of the close icon in BottomPanel for better alignment. - Modified layout options in Record component to streamline pagination controls. --- .../src/components/monitor/BottomPanel.vue | 39 +++++++++++++++---- .../components/monitor/components/Record.vue | 2 +- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/dag/src/components/monitor/BottomPanel.vue b/packages/dag/src/components/monitor/BottomPanel.vue index be80a1fc30..8748b48bd2 100644 --- a/packages/dag/src/components/monitor/BottomPanel.vue +++ b/packages/dag/src/components/monitor/BottomPanel.vue @@ -152,7 +152,7 @@ export default { key="bottomPanel" v-model="currentTab" style="--el-tabs-padding-left: 1rem" - class="setting-tabs h-100 flex-1 flex w-100" + class="setting-tabs h-100 flex-1 flex w-100 monitor-bottom-tabs" > - + - close + + +
@@ -341,12 +348,30 @@ $headerHeight: 40px; } .close-icon { position: absolute; - right: 16px; - top: 10px; + right: 12px; + top: 6px; } .tabs-header__hidden { :deep(.el-tabs__header) { display: none; } } + +.monitor-bottom-tabs { + :deep(.el-tabs__content) { + z-index: 1; + } +} + +.monitor-log-pane { + :deep(.log-container) { + min-width: 1000px; + .node-list { + position: sticky; + left: 0; + background-color: #fff; + z-index: 11; + } + } +} diff --git a/packages/dag/src/components/monitor/components/Record.vue b/packages/dag/src/components/monitor/components/Record.vue index f042a3adde..e75d16f87e 100644 --- a/packages/dag/src/components/monitor/components/Record.vue +++ b/packages/dag/src/components/monitor/components/Record.vue @@ -148,7 +148,7 @@ export default { :remote-method="remoteMethod" :columns="columns" :page-options="{ - layout: 'total, ->, prev, pager, next, sizes, jumper', + layout: 'total, ->, prev, pager, next, sizes', }" height="100%" hide-on-single-page From 5979733f67afa0a93c037381d15adfc990e3fc5b Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 12:13:26 +0800 Subject: [PATCH 04/10] refactor: add Vue 3 dependencies and clean up ConditionBox component - Added Vue 3 as a dependency in package.json and pnpm-lock.yaml. - Removed unused TableParams interface from ConditionBox.vue to streamline the code. --- packages/business/package.json | 1 + .../src/views/verification/components/ConditionBox.vue | 8 -------- pnpm-lock.yaml | 3 +++ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/business/package.json b/packages/business/package.json index 79c08d6268..7ac83afbd7 100644 --- a/packages/business/package.json +++ b/packages/business/package.json @@ -21,6 +21,7 @@ "lodash": "^4.17.15", "qs": "^6.11.0", "tiny-emitter": "^2.1.0", + "vue": "^3.0.0", "vue-json-viewer": "^2.2.15", "vue-virtual-scroller": "2.0.0-beta.8", "vuex": "^4.0.2" diff --git a/packages/business/src/views/verification/components/ConditionBox.vue b/packages/business/src/views/verification/components/ConditionBox.vue index 11fd6e6f2d..f10e07acf3 100644 --- a/packages/business/src/views/verification/components/ConditionBox.vue +++ b/packages/business/src/views/verification/components/ConditionBox.vue @@ -125,14 +125,6 @@ interface TableFilter { nodeId?: string } -interface TableParams { - nodeId: string - fields: any[] - page: number - pageSize: number - tableFilter?: string -} - interface ApiResult { data: ApiResponse } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9597f101e3..e612c4e674 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -442,6 +442,9 @@ importers: tiny-emitter: specifier: ^2.1.0 version: 2.1.0 + vue: + specifier: ^3.0.0 + version: 3.5.13(typescript@5.8.3) vue-json-viewer: specifier: ^2.2.15 version: 2.2.22(vue@3.5.13(typescript@5.8.3)) From bddd89eae0a3d502f1865efdb36d3dd6419d6560 Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 14:42:29 +0800 Subject: [PATCH 05/10] chore: update element-plus dependency to version 2.9.10 in package.json and pnpm-lock.yaml - Bumped element-plus from version 2.9.8 to 2.9.10 to incorporate the latest features and fixes. - Updated all relevant references in pnpm-lock.yaml to reflect the new version. --- package.json | 4 ++-- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 98c68dacd4..568d445108 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "nb": "node scripts/worktree-checkout.js" }, "dependencies": { - "element-plus": "^2.9.8", + "element-plus": "^2.9.10", "lodash-es": "^4.17.21", "vue-router": "^4.0.8" }, @@ -61,7 +61,7 @@ "@formily/reactive-vue": "^2.3.0", "@formily/shared": "^2.3.0", "@formily/vue": "^2.3.0", - "element-plus": "^2.9.8", + "element-plus": "^2.9.10", "vue": "^3.4.29", "vue-virtual-scroller": "2.0.0-beta.8" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e612c4e674..e00c7174e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ overrides: '@formily/reactive-vue': ^2.3.0 '@formily/shared': ^2.3.0 '@formily/vue': ^2.3.0 - element-plus: ^2.9.8 + element-plus: ^2.9.10 vue: ^3.4.29 vue-virtual-scroller: 2.0.0-beta.8 @@ -27,8 +27,8 @@ importers: .: dependencies: element-plus: - specifier: ^2.9.8 - version: 2.9.8(vue@3.5.13(typescript@5.8.3)) + specifier: ^2.9.10 + version: 2.9.10(vue@3.5.13(typescript@5.8.3)) lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -175,8 +175,8 @@ importers: specifier: ^5.0.2 version: 5.6.0 element-plus: - specifier: ^2.9.8 - version: 2.9.8(vue@3.5.13(typescript@5.8.3)) + specifier: ^2.9.10 + version: 2.9.10(vue@3.5.13(typescript@5.8.3)) github-markdown-css: specifier: ^4.0.0 version: 4.0.0 @@ -311,8 +311,8 @@ importers: specifier: ^5.0.2 version: 5.6.0 element-plus: - specifier: ^2.9.8 - version: 2.9.8(vue@3.5.13(typescript@5.8.3)) + specifier: ^2.9.10 + version: 2.9.10(vue@3.5.13(typescript@5.8.3)) github-markdown-css: specifier: ^4.0.0 version: 4.0.0 @@ -443,7 +443,7 @@ importers: specifier: ^2.1.0 version: 2.1.0 vue: - specifier: ^3.0.0 + specifier: ^3.4.29 version: 3.5.13(typescript@5.8.3) vue-json-viewer: specifier: ^2.2.15 @@ -653,8 +653,8 @@ importers: specifier: ^4.6.0 version: 4.9.0 element-plus: - specifier: ^2.9.8 - version: 2.9.8(vue@3.5.13(typescript@5.8.3)) + specifier: ^2.9.10 + version: 2.9.10(vue@3.5.13(typescript@5.8.3)) highlight.js: specifier: ^11.9.0 version: 11.9.0 @@ -2756,8 +2756,8 @@ packages: electron-to-chromium@1.5.138: resolution: {integrity: sha512-FWlQc52z1dXqm+9cCJ2uyFgJkESd+16j6dBEjsgDNuHjBpuIzL8/lRc0uvh1k8RNI6waGo6tcy2DvwkTBJOLDg==} - element-plus@2.9.8: - resolution: {integrity: sha512-srViUaUdfblBKGMeuEPiXxxKlH5aUmKqEwmhb/At9Sj91DbU6od/jYN1955cTnzt3wTSA7GfnZF7UiRX9sdRHg==} + element-plus@2.9.10: + resolution: {integrity: sha512-W2v9jWnm1kl/zm4bSvCh8aFCVlxvhG3fmqiDZwyd6WQiWGE595J/mpjcCggEr+49QDgIymhXrpPMOPPSARUbng==} peerDependencies: vue: ^3.4.29 @@ -6283,7 +6283,7 @@ snapshots: '@formily/reactive-vue': 2.3.3(vue@3.5.13(typescript@5.8.3)) '@formily/shared': 2.3.3 '@formily/vue': 2.3.3(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) - element-plus: 2.9.8(vue@3.5.13(typescript@5.8.3)) + element-plus: 2.9.10(vue@3.5.13(typescript@5.8.3)) resize-observer-polyfill: 1.5.1 vue: 3.5.13(typescript@5.8.3) vue-slicksort: 1.2.0(vue@3.5.13(typescript@5.8.3)) @@ -7713,7 +7713,7 @@ snapshots: electron-to-chromium@1.5.138: {} - element-plus@2.9.8(vue@3.5.13(typescript@5.8.3)): + element-plus@2.9.10(vue@3.5.13(typescript@5.8.3)): dependencies: '@ctrl/tinycolor': 3.6.1 '@element-plus/icons-vue': 2.3.1(vue@3.5.13(typescript@5.8.3)) From 40921747090b098d890fc58d1ae3e9f6d9cb7d35 Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 17:03:43 +0800 Subject: [PATCH 06/10] refactor: improve checkAll function logic in TableSelector component - Updated the checkAll function to differentiate between table and selected types more clearly. - Simplified the logic for setting checked values based on the type, enhancing code readability and maintainability. --- .../src/components/form/table-selector/TableSelector.vue | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/dag/src/components/form/table-selector/TableSelector.vue b/packages/dag/src/components/form/table-selector/TableSelector.vue index 53fa139b58..bcbcc09ff2 100644 --- a/packages/dag/src/components/form/table-selector/TableSelector.vue +++ b/packages/dag/src/components/form/table-selector/TableSelector.vue @@ -180,10 +180,11 @@ const loadSchema = async () => { } const checkAll = (val: boolean, type: 'table' | 'selected') => { - const target = type === 'table' ? table : selected - target.value.checked = val ? target.value.tables : [] - target.value.isCheckAll = val - emit('change', selected.value.tables) + if (type === 'table') { + table.value.checked = val ? leftTableData.value : [] + } else { + selected.value.checked = val ? selected.value.tables : [] + } } const checkedChange = (type: 'table' | 'selected') => { From 73ec0d334678039c7eeb879ba878aecc72ab1c34 Mon Sep 17 00:00:00 2001 From: Feynman Date: Mon, 12 May 2025 17:37:03 +0800 Subject: [PATCH 07/10] refactor: rename Kafka connection option to Kafka-Enhanced for clarity - Updated the connection option from 'Kafka' to 'Kafka-Enhanced' in SceneDialog.vue. - Adjusted corresponding i18n translation key to reflect the new naming convention. --- .../src/components/create-connection/SceneDialog.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/business/src/components/create-connection/SceneDialog.vue b/packages/business/src/components/create-connection/SceneDialog.vue index dd255ff3ba..330e9bbb39 100644 --- a/packages/business/src/components/create-connection/SceneDialog.vue +++ b/packages/business/src/components/create-connection/SceneDialog.vue @@ -80,7 +80,7 @@ export default { 'Clickhouse', 'Elasticsearch', 'Dummy', - 'Kafka', + 'Kafka-Enhanced', 'Doris', 'BigQuery', ], @@ -178,7 +178,9 @@ export default { 'packages_business_create_connection_elasticsearch_desc', ), Dummy: i18n.t('packages_business_create_connection_dummy_desc'), - Kafka: i18n.t('packages_business_create_connection_kafka_desc'), + 'Kafka-Enhanced': i18n.t( + 'packages_business_create_connection_kafka_desc', + ), Doris: i18n.t('packages_business_create_connection_doris_desc'), 'MongoDB Atlas': i18n.t( 'packages_business_create_connection_mongodbatlas_desc', From cd04d245f625df5d7104aade4cfa8350a1fc5a6c Mon Sep 17 00:00:00 2001 From: Feynman Date: Tue, 13 May 2025 15:40:48 +0800 Subject: [PATCH 08/10] refactor: enhance component structure and functionality across multiple files - Added new components ElEmpty and ElText to the Vue declaration in components.d.ts for better integration with Element Plus. - Removed the unused right.svg icon file to clean up the assets. - Introduced new background color utility classes in utilities.scss for improved styling options. - Updated Form.vue to include additional functionality for task selection and improved form handling. - Enhanced CollateMap.vue and ConditionBox.vue components with new props and event emissions for better interactivity. - Refactored ConsolePanel.vue to streamline logging functionality and improve user experience. - Updated InfiniteSelect.vue and JSON/SQL editors to enhance styling and usability. - Cleaned up FieldDialog.vue for better code readability and consistency in icon usage. --- apps/daas/src/assets/icons/svg/right.svg | 11 - apps/daas/src/components.d.ts | 2 + packages/assets/styles/utilities.scss | 16 +- .../business/src/views/verification/Form.vue | 979 ++++---- .../verification/components/CollateMap.vue | 15 +- .../verification/components/ConditionBox.vue | 2037 ++++++----------- .../src/components/migration/ConsolePanel.vue | 211 +- .../infinite-select/InfiniteSelect.vue | 7 +- .../form/src/components/json-editor/index.jsx | 2 +- .../form/src/components/sql-editor/index.jsx | 2 +- .../verify-fields-dialog/FieldDialog.vue | 2 +- 11 files changed, 1419 insertions(+), 1865 deletions(-) delete mode 100644 apps/daas/src/assets/icons/svg/right.svg diff --git a/apps/daas/src/assets/icons/svg/right.svg b/apps/daas/src/assets/icons/svg/right.svg deleted file mode 100644 index 7de3a76480..0000000000 --- a/apps/daas/src/assets/icons/svg/right.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - jiantou_yemian_xiangyou - - - - - - - - \ No newline at end of file diff --git a/apps/daas/src/components.d.ts b/apps/daas/src/components.d.ts index 3a802bb466..d237710e02 100644 --- a/apps/daas/src/components.d.ts +++ b/apps/daas/src/components.d.ts @@ -34,6 +34,7 @@ declare module 'vue' { ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElHeader: typeof import('element-plus/es')['ElHeader'] @@ -76,6 +77,7 @@ declare module 'vue' { ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabs: typeof import('element-plus/es')['ElTabs'] ElTag: typeof import('element-plus/es')['ElTag'] + ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTree: typeof import('element-plus/es')['ElTree'] ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] diff --git a/packages/assets/styles/utilities.scss b/packages/assets/styles/utilities.scss index 9b690ede12..ba50da9849 100644 --- a/packages/assets/styles/utilities.scss +++ b/packages/assets/styles/utilities.scss @@ -12557,4 +12557,18 @@ .-z-10 { z-index: -10; -} \ No newline at end of file +} + +.bg-gray-50 { + background-color: rgb(249 250 251); +} + +.bg-gray-100 { + background-color: rgb(243 244 246); +} + +.bg-gray-200 { + background-color: rgb(229 231 235); +} + + diff --git a/packages/business/src/views/verification/Form.vue b/packages/business/src/views/verification/Form.vue index 554d00bc59..001cb2f574 100644 --- a/packages/business/src/views/verification/Form.vue +++ b/packages/business/src/views/verification/Form.vue @@ -1,11 +1,18 @@ + + + + + + + @@ -1105,4 +1112,44 @@ provide('formData', form) margin-top: 8px; } } + +.has-sticky { + --sticky-top: 0px; + :deep(.el-collapse-item__header) { + position: sticky; + top: var(--sticky-top); + z-index: 10; + } +} + +.el-collapse { + &.last-item-noborder { + border-bottom: none; + :deep(.el-collapse-item:last-child) { + margin-bottom: 0; + .el-collapse-item__header, + .el-collapse-item__wrap { + border-bottom: none; + } + } + } +} + +.condition-panel { + :deep(.condition-footer) { + bottom: 72px; + backdrop-filter: blur(12px); + background-color: rgba(255, 255, 255, 0.8); + z-index: 10; + } + &.is-active { + :deep(.el-collapse-item__wrap) { + overflow: unset; + } + } +} + +.content-footer { + height: 72px; +} diff --git a/packages/business/src/views/verification/components/CollateMap.vue b/packages/business/src/views/verification/components/CollateMap.vue index aa58029a2c..c67b725f2a 100644 --- a/packages/business/src/views/verification/components/CollateMap.vue +++ b/packages/business/src/views/verification/components/CollateMap.vue @@ -17,14 +17,17 @@ export default defineComponent({ }, fields: { type: Array, - default: () => [], }, sortColumn: { type: String, required: true, }, + loading: { + type: Boolean, + default: false, + }, }, - emits: ['update:value'], + emits: ['update:value', 'visibleChange'], setup(props, { emit }) { const setCharset = (value) => { selectedFields.value.forEach((key) => { @@ -62,8 +65,10 @@ export default defineComponent({ }) const sortFields = computed(() => { - return props.fields.filter((field) => - sortColumns.value.includes(field.field_name), + return ( + props.fields?.filter((field) => + sortColumns.value.includes(field.field_name), + ) || [] ) }) @@ -87,6 +92,8 @@ export default defineComponent({ :options="sortFields" :placeholder="$t('packages_business_please_select_field')" class="flex-1" + :loading="loading" + @visible-change="$emit('visibleChange', $event)" /> +import { InfoFilled, Loading, Right } from '@element-plus/icons-vue' import { action } from '@formily/reactive' import { connectionsApi, metadataInstancesApi } from '@tap/api' import { GitBook, VCodeEditor } from '@tap/component' import SwitchNumber from '@tap/component/src/SwitchNumber.vue' -import { AsyncSelect, SchemaForm } from '@tap/form' +import { AsyncSelect, JsonEditor, SqlEditor } from '@tap/form' import i18n from '@tap/i18n' import { uuid } from '@tap/shared' import { ElMessage, ElMessageBox } from 'element-plus' @@ -24,6 +25,7 @@ import { ref, watch, } from 'vue' +import { DatabaseIcon } from '../../../components' import { CONNECTION_STATUS_MAP } from '../../../shared' import { inspectMethod as inspectMethodMap } from '../const' import CollateMap from './CollateMap.vue' @@ -71,9 +73,9 @@ interface Props { } interface Emits { - (e: 'update:jointErrorMessage', value: string): void (e: 'update:errorMessageLevel', value: string): void (e: 'update:autoAddTableLoading', value: boolean): void + (e: 'openTaskSelect'): void } interface ApiResponse { @@ -125,29 +127,6 @@ interface TableFilter { nodeId?: string } -interface ApiResult { - data: ApiResponse -} - -interface FieldItem { - id: string - field_name: string - primary_key_position: number - data_type: string - primaryKey: boolean - unique: boolean - type: string - tapType: string -} - -interface NodeSchemaResponse { - items: { - fields: FieldItem[] - name: string - }[] - total: number -} - interface StageItem { id: string name: string @@ -160,8 +139,7 @@ interface StageItem { } const formData = inject('formData') - -const list = computed(() => formData.tasks) +const ConnectorMap = inject('ConnectorMap') // Props and Emits const props = withDefaults(defineProps(), { @@ -175,10 +153,7 @@ const emit = defineEmits() // Refs and Reactive State const showDoc = ref(false) const docPath = ref('') -// const list = ref([]) -const jointErrorMessage = ref('') const fieldsMap = reactive>({}) -const capabilitiesMap = reactive>({}) const autoAddTableLoading = ref(false) const dynamicSchemaMap = reactive>({}) const dialogAddScriptVisible = ref(false) @@ -192,694 +167,9 @@ const autoSuggestJoinFields = ref(true) const searchValue = ref('') const fieldDialog = ref() -// const list = computed(() => { -// return formData.tasks -// }) - -const formSchema = { - type: 'object', - properties: { - nameWrap: { - type: 'void', - 'x-component': 'FormGrid', - 'x-component-props': { - minColumns: 2, - maxColumns: 2, - columnGap: 16, - }, - properties: { - source: { - type: 'object', - 'x-component': 'FormGrid.GridColumn', - properties: { - databaseType: { - type: 'string', - 'x-display': 'hidden', - }, - fields: { - type: 'array', - 'x-display': 'hidden', - }, - nodeSchema: { - type: 'array', - 'x-display': 'hidden', - 'x-reactions': [ - `{{useAsyncDataSource(loadTableFieldList, 'value', $values.source)}}`, - { - target: 'source.conditions.*.key', - fulfill: { - state: { - loading: '{{$self.loading}}', - dataSource: '{{$self.value}}', - }, - }, - }, - ], - }, - enableCustomCommand: { - title: i18n.t( - 'packages_business_components_conditionbox_laiyuanbiaoshuju', - ), - type: 'boolean', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - className: 'item-control-horizontal', - layout: 'horizontal', - tooltip: i18n.t( - 'packages_business_components_conditionbox_enableCustomCommand_tip', - ), - }, - 'x-component': 'Switch', - default: false, - 'x-reactions': [ - { - fulfill: { - state: { - visible: `{{$values.source.capabilities && $values.source.capabilities.some(item => item.id === 'execute_command_function')}}`, - }, - }, - }, - ], - }, - customCommand: { - type: 'object', - properties: { - command: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'string', - default: 'executeQuery', - 'x-decorator': 'FormItem', - 'x-component': 'Radio.Group', - enum: [ - { label: i18n.t('public_query'), value: 'executeQuery' }, - { label: i18n.t('public_aggregate'), value: 'aggregate' }, - ], - 'x-reactions': { - dependencies: ['source.databaseType'], - fulfill: { - state: { - display: - '{{$deps[0].toLowerCase().includes("mongo")?"visible":"hidden"}}', - }, - }, - }, - }, - params: { - type: 'object', - properties: { - mongoQuery: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'void', - 'x-reactions': { - dependencies: [ - 'source.customCommand.command', - 'source.databaseType', - ], - fulfill: { - state: { - visible: - '{{$deps[1].toLowerCase().includes("mongo") && $deps[0]==="executeQuery"}}', - }, - }, - }, - properties: { - op: { - type: 'string', - default: 'find', - }, - collection: { - type: 'string', - 'x-reactions': { - fulfill: { - state: { - value: '{{$values.tableName}}', - }, - }, - }, - }, - filter: { - title: ' ', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'JsonEditor', - 'x-component-props': { - options: { - showPrintMargin: false, - useWrapMode: true, - }, - }, - }, - descWrap: { - type: 'void', - title: ' ', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - 'x-component': 'div', - 'x-component-props': { - class: 'flex align-center flex-wrap', - }, - properties: { - desc: { - type: 'void', - 'x-component': 'div', - 'x-component-props': { - style: { - color: '#909399', - }, - }, - 'x-content': i18n.t( - 'packages_dag_nodes_table_jinzhichiqu', - ), - }, - link: { - type: 'void', - 'x-component': 'Button', - 'x-component-props': { - text: true, - type: 'primary', - onClick: '{{openApiDrawer}}', - }, - 'x-content': i18n.t( - 'packages_business_view_more_apis', - ), - }, - }, - }, - }, - }, - mongoAgg: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'void', - 'x-reactions': { - dependencies: [ - 'source.customCommand.command', - 'source.databaseType', - ], - fulfill: { - state: { - visible: - '{{$deps[1].toLowerCase().includes("mongo") && $deps[0]==="aggregate"}}', - }, - }, - }, - properties: { - collection: { - type: 'string', - 'x-reactions': { - dependencies: ['source.tableName'], - fulfill: { - state: { - value: '{{$deps[0]}}', - }, - }, - }, - }, - pipeline: { - title: ' ', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'JsonEditor', - 'x-component-props': { - options: { - showPrintMargin: false, - useWrapMode: true, - }, - }, - }, - descWrap: { - type: 'void', - title: ' ', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - 'x-component': 'div', - 'x-component-props': { - class: 'flex align-center flex-wrap', - }, - properties: { - desc: { - type: 'void', - 'x-component': 'div', - 'x-component-props': { - style: { - color: '#909399', - }, - }, - 'x-content': i18n.t( - 'packages_dag_nodes_table_shiligro', - ), - }, - link: { - type: 'void', - 'x-component': 'Button', - 'x-component-props': { - text: true, - type: 'primary', - onClick: '{{openApiDrawer}}', - }, - 'x-content': i18n.t( - 'packages_business_view_more_apis', - ), - }, - }, - }, - }, - }, - sql: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'SqlEditor', - 'x-component-props': { - options: { showPrintMargin: false, useWrapMode: true }, - }, - 'x-reactions': { - dependencies: [ - 'source.enableCustomCommand', - 'source.databaseType', - ], - fulfill: { - state: { - visible: - '{{!!$deps[0] && !$deps[1].toLowerCase().includes("mongo")}}', - }, - }, - }, - }, - }, - }, - }, - 'x-reactions': [ - { - dependencies: ['source.enableCustomCommand'], - fulfill: { - state: { - visible: `{{$deps[0]}}`, - }, - }, - }, - ], - }, - }, - }, - target: { - type: 'object', - 'x-component': 'FormGrid.GridColumn', - properties: { - databaseType: { - type: 'string', - 'x-display': 'hidden', - }, - fields: { - type: 'array', - 'x-display': 'hidden', - }, - nodeSchema: { - type: 'array', - 'x-display': 'hidden', - 'x-reactions': [ - `{{useAsyncDataSource(loadTableFieldList, 'value', $values.target)}}`, - { - target: 'target.conditions.*.key', - fulfill: { - state: { - loading: '{{$self.loading}}', - dataSource: '{{$self.value}}', - }, - }, - }, - ], - }, - enableCustomCommand: { - title: i18n.t( - 'packages_business_components_conditionbox_mubiaobiaoshuju', - ), - type: 'boolean', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - className: 'item-control-horizontal', - layout: 'horizontal', - labelWrap: true, - tooltip: i18n.t( - 'packages_business_components_conditionbox_enableCustomCommand_tip', - ), - }, - 'x-component': 'Switch', - default: false, - 'x-reactions': [ - { - fulfill: { - state: { - visible: `{{$values.target.capabilities && $values.target.capabilities.some(item => item.id === 'execute_command_function')}}`, - }, - }, - }, - ], - }, - customCommand: { - type: 'object', - properties: { - command: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'string', - default: 'executeQuery', - 'x-decorator': 'FormItem', - 'x-component': 'Radio.Group', - enum: [ - { label: i18n.t('public_query'), value: 'executeQuery' }, - { label: i18n.t('public_aggregate'), value: 'aggregate' }, - ], - 'x-reactions': { - dependencies: ['target.databaseType'], - fulfill: { - state: { - display: - '{{$deps[0].toLowerCase().includes("mongo")?"visible":"hidden"}}', - }, - }, - }, - }, - params: { - type: 'object', - properties: { - mongoQuery: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'void', - 'x-reactions': { - dependencies: [ - 'target.customCommand.command', - 'target.databaseType', - ], - fulfill: { - state: { - visible: - '{{$deps[1].toLowerCase().includes("mongo") && $deps[0]==="executeQuery"}}', - }, - }, - }, - properties: { - op: { - type: 'string', - default: 'find', - }, - collection: { - type: 'string', - 'x-reactions': { - fulfill: { - state: { - value: '{{$values.tableName}}', - }, - }, - }, - }, - filter: { - title: ' ', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'JsonEditor', - 'x-component-props': { - options: { - showPrintMargin: false, - useWrapMode: true, - }, - }, - }, - descWrap: { - type: 'void', - title: ' ', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - 'x-component': 'div', - 'x-component-props': { - class: 'flex align-center flex-wrap', - }, - properties: { - desc: { - type: 'void', - 'x-component': 'div', - 'x-component-props': { - style: { - color: '#909399', - }, - }, - 'x-content': i18n.t( - 'packages_dag_nodes_table_jinzhichiqu', - ), - }, - link: { - type: 'void', - 'x-component': 'Button', - 'x-component-props': { - text: true, - type: 'primary', - onClick: '{{openApiDrawer}}', - }, - 'x-content': i18n.t( - 'packages_business_view_more_apis', - ), - }, - }, - }, - }, - }, - mongoAgg: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'void', - 'x-reactions': { - dependencies: [ - 'target.customCommand.command', - 'target.databaseType', - ], - fulfill: { - state: { - visible: - '{{$deps[1].toLowerCase().includes("mongo") && $deps[0]==="aggregate"}}', - }, - }, - }, - properties: { - collection: { - type: 'string', - 'x-reactions': { - dependencies: ['target.tableName'], - fulfill: { - state: { - value: '{{$deps[0]}}', - }, - }, - }, - }, - pipeline: { - title: ' ', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'JsonEditor', - 'x-component-props': { - options: { - showPrintMargin: false, - useWrapMode: true, - }, - }, - }, - descWrap: { - type: 'void', - title: ' ', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - colon: false, - feedbackLayout: 'none', - }, - 'x-component': 'div', - 'x-component-props': { - class: 'flex align-center flex-wrap', - }, - properties: { - desc: { - type: 'void', - 'x-component': 'div', - 'x-component-props': { - style: { - color: '#909399', - }, - }, - 'x-content': i18n.t( - 'packages_dag_nodes_table_shiligro', - ), - }, - link: { - type: 'void', - 'x-component': 'Button', - 'x-component-props': { - text: true, - type: 'primary', - onClick: '{{openApiDrawer}}', - }, - 'x-content': i18n.t( - 'packages_business_view_more_apis', - ), - }, - }, - }, - }, - }, - sql: { - title: ' ', - 'x-decorator-props': { - colon: false, - }, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'SqlEditor', - 'x-component-props': { - options: { showPrintMargin: false, useWrapMode: true }, - }, - 'x-reactions': { - dependencies: [ - 'target.enableCustomCommand', - 'target.databaseType', - ], - fulfill: { - state: { - visible: - '{{!!$deps[0] && !$deps[1].toLowerCase().includes("mongo")}}', - }, - }, - }, - }, - }, - }, - }, - 'x-reactions': [ - { - dependencies: ['target.enableCustomCommand'], - fulfill: { - state: { - visible: `{{$deps[0]}}`, - }, - }, - }, - ], - }, - }, - }, - }, - }, - }, -} - -const schemaScope = { - $supportFilterFunction: - props.inspectMethod === 'row_count' - ? 'count_by_partition_filter_function' - : 'query_by_advance_filter_function', - useAsyncDataSource: (service, fieldName = 'dataSource', ...serviceParams) => { - return (field) => { - field.loading = true - service({ field }, ...serviceParams).then( - action.bound((data) => { - if (fieldName === 'value') { - field.setValue(data) - } else field[fieldName] = data - field.loading = false - }), - ) - } - }, - async loadTableFieldList(obj, item) { - try { - if (!item.connectionId || !item.table) return [] - let fields = item.fields - if (!fields?.length) { - const params = { - where: { - meta_type: 'table', - sourceType: 'SOURCE', - original_name: item.table, - 'source._id': item.connectionId, - }, - limit: 1, - } - const data = await metadataInstancesApi.tapTables({ - filter: JSON.stringify(params), - }) - fields = Object.values(data.items[0]?.nameFieldMap || {}).map((t) => { - return { - id: t.id, - label: t.fieldName || t.field_name, - value: t.fieldName || t.field_name, - field_name: t.fieldName || t.field_name, - primary_key_position: t.primaryKey, - data_type: t.dataType || t.data_type, - primaryKey: t.primaryKey, - unique: t.unique, - type: t.dataType || t.data_type, - tapType: JSON.stringify(t.tapType), - } - }) - } - const result = fields - - if (result.length) { - item.fields = result - } - - return result - } catch { - return [] - } - }, - openApiDrawer: (path) => { - docPath.value = isString(path) ? path : '' - showDoc.value = true - }, -} - // Computed Properties +const list = computed(() => formData.tasks) + const flowStages = computed(() => { const types = props.isDB ? ['database'] : ['table'] return props.allStages.filter((stg) => types.includes(stg.type)) @@ -911,55 +201,25 @@ const totalPages = computed(() => { return Math.ceil(filteredList.value.length / pageSize.value) }) -const nullsLastState = computed(() => { - return Object.keys(capabilitiesMap).reduce( - (cur, pre) => { - const tags = capabilitiesMap[pre]?.tags || [] - if (tags.includes('NullsLast')) { - cur[pre] = true - } - return cur - }, - {} as Record, - ) -}) - -// Watchers -// watch( -// () => props.taskId, -// (v1, v2) => { -// if (v1 !== v2) { -// clearList() -// } -// }, -// ) - -// watch( -// () => props.data, -// () => { -// loadList() -// }, -// { deep: true }, -// ) - -watch( - list, - () => { - debounceValidate() - // Reset to page 1 if list is empty - if (list.value.length === 0) { - currentPage.value = 1 - } - }, - { deep: true }, -) - watch(searchValue, () => { // Reset to page 1 when search filter changes currentPage.value = 1 }) // Methods +const openApiDrawer = (path: string) => { + docPath.value = isString(path) ? path : '' + showDoc.value = true +} + +const hasCapability = (obj, capability) => { + if (!obj.databaseType) return false + + const item = ConnectorMap.value[obj.databaseType] + + return item?.capabilityMap[capability] +} + const getConnectionsListMethod = async ( filter: any, ): Promise> => { @@ -1369,9 +629,6 @@ const autoAddTable = async () => { const connectionIds = [...connectionSet] - // 加载数据源的Capabilities - const capabilitiesMap = await getCapabilities(connectionIds) - if (!matchNodeList.length) { autoAddTableLoading.value = false updateAutoAddTableLoading() @@ -1423,7 +680,6 @@ const autoAddTable = async () => { const sourceTableList = Object.keys(tableNameRelation) sourceTableList.forEach((ge: string) => { const item = getItemOptions() - // 填充source item.source.nodeId = source item.source.nodeName = sourceName item.source.databaseType = sourceDatabaseType @@ -1431,9 +687,7 @@ const autoAddTable = async () => { item.source.connectionName = sourceConnectionName item.source.currentLabel = `${sourceName} / ${sourceConnectionName}` item.source.table = ge // findTable.original_name - item.source.capabilities = - capabilitiesMap[sourceConnectionId]?.capabilities || [] - // 填充target + item.target.nodeId = target item.target.nodeName = targetName item.target.databaseType = targetDatabaseType @@ -1441,8 +695,6 @@ const autoAddTable = async () => { item.target.connectionName = targetConnectionName item.target.currentLabel = `${targetName} / ${targetConnectionName}` item.target.table = tableNameRelation[ge] // findTargetTable.original_name - item.target.capabilities = - capabilitiesMap[targetConnectionId]?.capabilities || [] const updateList = cloneDeep( updateConditionFieldMap[tableNameRelation[ge]] || [], @@ -1578,25 +830,12 @@ const handleChangeConnection = async (opt: any, item: any) => { item.sortColumn = '' // 重选连接,清空表 item.databaseType = opt.databaseType - if (capabilitiesMap?.[opt.attrs?.connectionId]) { - item.capabilities = - capabilitiesMap[opt.attrs?.connectionId]?.capabilities || [] - } else { - const { capabilities, tags } = await getConnectionCapabilities( - opt.attrs?.connectionId, - ) - item.capabilities = capabilities - capabilitiesMap[opt.attrs?.connectionId] = { - capabilities, - tags, - } - } - if (!props.taskId) { item.connectionName = opt.attrs?.connectionName item.currentLabel = item.connectionName return } + const { nodeId, nodeName, connectionName } = opt.attrs || {} item.nodeId = nodeId item.nodeName = nodeName @@ -1701,9 +940,6 @@ const handleChangeTable = ( item.target.currentLabel = `${targetName} / ${targetConnectionName}` item.target.table = tableName ? tableName : tableNameRelation[val] - item.target.capabilities = - capabilitiesMap[targetConnectionId]?.capabilities || [] - const key = [target || '', targetConnectionId, item.target.table].join() if (fieldsMap[key]) { item.target.fields = fieldsMap[key] @@ -1975,11 +1211,11 @@ const validate = async () => { const validateCapabilities = (tasks: any[], capability: string) => { const noSupportList = new Set() tasks.forEach((item) => { - if (!item.source.capabilities?.find((c: any) => c.id === capability)) { + if (!hasCapability(item.source, capability)) { noSupportList.add(item.source.databaseType) } - if (!item.target.capabilities?.find((c: any) => c.id === capability)) { + if (!hasCapability(item.target, capability)) { noSupportList.add(item.target.databaseType) } }) @@ -2122,11 +1358,11 @@ const handleChangeFields = (data: any[] = [], id: string) => { item.target.columns = data.map((t) => t.target) } -const handleFocus = (opt: any = {}, visible) => { +const onVisibleChange = (opt: any = {}, visible) => { if (!visible || opt.fields?.length) { return } - + opt.fieldsLoading = true const connectionId = opt.connectionId const params = { where: { @@ -2162,50 +1398,12 @@ const handleFocus = (opt: any = {}, visible) => { }, ) }) -} - -const getCapabilities = async (connectionIds: string[] = []) => { - if (!connectionIds.length) return - - const map = {} - - await Promise.all( - connectionIds.map(async (id) => { - const { capabilities, tags } = await getConnectionCapabilities(id) - map[id] = { - capabilities, - tags, - } - }), - ) - - // 重置 capabilitiesMap 后再更新 - Object.keys(capabilitiesMap).forEach((key) => { - delete capabilitiesMap[key] - }) - Object.assign(capabilitiesMap, map) - - return map -} - -const getMatchCapabilitiesMap = () => { - const list = cloneDeep(props.allStages) - return list.reduce((cur: any, pre: any) => { - cur[pre.connectionId] = pre.attrs?.capabilities - return cur - }, {}) -} - -const getConnectionCapabilities = async (id: string) => { - const data = await connectionsApi.getNoSchema(id) - return { - capabilities: data?.capabilities || [], - tags: data?.definitionTags || [], - } + .finally(() => { + opt.fieldsLoading = false + }) } const updateErrorMsg = (msg: string, level = '') => { - emit('update:jointErrorMessage', msg) emit('update:errorMessageLevel', level) } @@ -2228,6 +1426,26 @@ const toggleCollate = (item: any, value: boolean) => { } } +const handleChangeCustomCommand = (val: string, item: any) => { + if (val) { + let { customCommand } = item + + if (!customCommand) { + customCommand = { + command: 'executeQuery', + params: {}, + } + item.customCommand = customCommand + } + } else { + item.customCommand = null + } +} + +const isNullsLast = (item: any) => { + return ConnectorMap.value[item.databaseType]?.isNullsLast +} + // Lifecycle Hooks onMounted(() => { loadDoc() @@ -2238,513 +1456,736 @@ defineExpose({ autoAddTable, getList, validate, - getCapabilities, }) + + -
- +
+
+
-
-
- -
+ + + + -
- - - {{ - $t('packages_business_components_fieldbox_quanziduan') - }} - {{ - $t('packages_business_connections_databaseform_zidingyi') - }} - - - - {{ - $t('packages_business_components_conditionbox_chakanzidingyi') - }} - ({{ item.source.columns ? item.source.columns.length : 0 }}) - -
-
- {{ $t('packages_business_verification_advanceVerify') }} - -
-
- - {{ $t('packages_business_verification_addJS') }} - - -
-
-
{{ item.webScript }}
+ +
+
+
{{ item.webScript }}
+
- - - -
- -
- - -
-
-
- function validate(sourceRow){ + {{ + $t('packages_business_verification_addTable') + }} + {{ $t('packages_business_verification_button_auto_add_table') }} + + +