From 5c66bf5e099871c4d1e6e9c1a1acc0aa4484186a Mon Sep 17 00:00:00 2001 From: Tara <39621793+Tara8573@users.noreply.github.com> Date: Thu, 24 Sep 2026 21:30:42 +0800 Subject: [PATCH] feat(postgres): browse PostgreSQL event triggers --- .../objects/EventTriggerDetailsDialog.vue | 132 ++++++++++++++++++ .../src/components/sidebar/ConnectionTree.vue | 25 ++++ .../sidebar/SidebarTreeRuntimeHost.vue | 16 ++- .../src/components/sidebar/TreeItem.vue | 4 + apps/desktop/src/i18n/locales/az.ts | 13 ++ apps/desktop/src/i18n/locales/en.ts | 13 ++ apps/desktop/src/i18n/locales/es.ts | 13 ++ apps/desktop/src/i18n/locales/it.ts | 13 ++ apps/desktop/src/i18n/locales/ja.ts | 13 ++ apps/desktop/src/i18n/locales/ko.ts | 13 ++ apps/desktop/src/i18n/locales/pt-BR.ts | 13 ++ apps/desktop/src/i18n/locales/ru.ts | 13 ++ apps/desktop/src/i18n/locales/tr.ts | 13 ++ apps/desktop/src/i18n/locales/zh-CN.ts | 13 ++ apps/desktop/src/i18n/locales/zh-TW.ts | 13 ++ apps/desktop/src/lib/backend/api.ts | 1 + apps/desktop/src/lib/backend/http.ts | 5 + apps/desktop/src/lib/backend/tauri.ts | 5 + .../lib/sidebar/treeLoadedChildrenMarker.ts | 2 +- apps/desktop/src/lib/sidebar/treeNodeClick.ts | 6 +- apps/desktop/src/lib/sidebar/treeNodeGroup.ts | 1 + apps/desktop/src/lib/sidebar/treeNodeIcon.ts | 4 + .../connectionStore.metadataLoading.spec.ts | 6 +- apps/desktop/src/stores/connectionStore.ts | 48 +++++++ apps/desktop/src/types/database.ts | 16 ++- .../dbx-core/assets/docs-export.manifest.json | 2 +- crates/dbx-core/src/schema/kingbase.rs | 61 ++++++++ crates/dbx-core/src/schema/mod.rs | 35 +++++ crates/dbx-drivers/src/db/postgres.rs | 82 ++++++++++- crates/dbx-types/src/types.rs | 27 ++++ crates/dbx-web/src/main.rs | 1 + crates/dbx-web/src/routes/schema.rs | 11 ++ src-tauri/src/commands/schema.rs | 9 ++ src-tauri/src/lib.rs | 1 + 34 files changed, 632 insertions(+), 11 deletions(-) create mode 100644 apps/desktop/src/components/objects/EventTriggerDetailsDialog.vue diff --git a/apps/desktop/src/components/objects/EventTriggerDetailsDialog.vue b/apps/desktop/src/components/objects/EventTriggerDetailsDialog.vue new file mode 100644 index 0000000000..40763abd09 --- /dev/null +++ b/apps/desktop/src/components/objects/EventTriggerDetailsDialog.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/desktop/src/components/sidebar/ConnectionTree.vue b/apps/desktop/src/components/sidebar/ConnectionTree.vue index f9b5080d05..c6f682c6f4 100644 --- a/apps/desktop/src/components/sidebar/ConnectionTree.vue +++ b/apps/desktop/src/components/sidebar/ConnectionTree.vue @@ -9,6 +9,7 @@ import { useSettingsStore } from "@/stores/settingsStore"; import { useToast } from "@/composables/useToast"; import type { ColumnInfo, ObjectSourceKind, QueryTab, TableInfo, TableNameFilter, TreeNode, TreeNodeType } from "@/types/database"; import type { ElasticsearchIndexMetadataKind } from "@/lib/backend/tauri"; +import { listEventTriggers } from "@/lib/backend/api"; import { filterLocallySearchedTables, createSidebarSearchSubtreePreserver, @@ -68,6 +69,7 @@ import SidebarTreeItemDialogs from "./SidebarTreeItemDialogs.vue"; import SidebarTableVGroupDialog from "./SidebarTableVGroupDialog.vue"; import InstallExtensionDialog from "@/components/objects/InstallExtensionDialog.vue"; import ExtensionDetailsDialog from "@/components/objects/ExtensionDetailsDialog.vue"; +import EventTriggerDetailsDialog from "@/components/objects/EventTriggerDetailsDialog.vue"; import { RecycleScroller } from "vue-virtual-scroller"; import "vue-virtual-scroller/dist/vue-virtual-scroller.css"; import LightDropdown from "@/components/ui/LightDropdown.vue"; @@ -133,6 +135,8 @@ const sidebarInstallExtensionTarget = ref(null); const sidebarInstallExtensionDialogRef = ref | null>(null); const sidebarExtensionDetailsTarget = ref(null); const sidebarExtensionDetailsDialogRef = ref | null>(null); +const sidebarEventTriggerDetailsTarget = ref(null); +const sidebarEventTriggerDetailsDialogRef = ref | null>(null); const sidebarTreeRuntimeHostRef = ref(null); const sidebarTreeRuntime = createSidebarTreeRuntime(); const sidebarTreeRuntimeInitialNode: TreeNode = { id: "__sidebar-runtime__", label: "", type: "connection-group" }; @@ -2038,6 +2042,25 @@ async function openSidebarExtensionDetails(node: TreeNode) { sidebarExtensionDetailsDialogRef.value?.show(); } +async function openSidebarEventTriggerDetails(node: TreeNode) { + sidebarEventTriggerDetailsTarget.value = createSidebarActionTarget(node); + await nextTick(); + sidebarEventTriggerDetailsDialogRef.value?.show(); + // 打开详情时静默拉取最新事件触发器数据,只更新当前节点的 meta 与对话框, + // 不重建整个侧边栏列表(避免每次打开都强制刷新触发器列表)。 + if (!node.connectionId || !node.database) return; + try { + const triggers = await listEventTriggers(node.connectionId, node.database); + const fresh = triggers.find((et) => et.name === node.label); + if (fresh) { + node.meta = fresh; + sidebarEventTriggerDetailsTarget.value = createSidebarActionTarget({ ...node, meta: fresh }); + } + } catch { + // 拉取失败时保留首次打开的缓存值。 + } +} + function beginSidebarAction(): number { sidebarActionGeneration += 1; sidebarDdlOpen.value = false; @@ -2557,6 +2580,7 @@ defineExpose({ focusSearch, createNewGroup, collapseAllTreeNodes, locateTabInSid @open-dialog-controller="updateSidebarTreeItemDialogController" @open-install-extension="openSidebarInstallExtension" @open-extension-details="openSidebarExtensionDetails" + @open-event-trigger-details="openSidebarEventTriggerDetails" />