feat: 查询超时错误页支持跳转修改超时时间
This commit is contained in:
6 files changed
+37
-3
No files matched your search
@@ -12,6 +12,7 @@ import ContentArea from "@/components/layout/ContentArea.vue";
|
|||||||
import AppDialogs from "@/components/layout/AppDialogs.vue";
|
import AppDialogs from "@/components/layout/AppDialogs.vue";
|
||||||
import WelcomeScreen from "@/components/layout/WelcomeScreen.vue";
|
import WelcomeScreen from "@/components/layout/WelcomeScreen.vue";
|
||||||
import DdlViewDialog from "@/components/objects/DdlViewDialog.vue";
|
import DdlViewDialog from "@/components/objects/DdlViewDialog.vue";
|
||||||
|
import type { ConfigTab } from "@/components/connection/ConnectionDialog.vue";
|
||||||
import { useConnectionStore } from "@/stores/connectionStore";
|
import { useConnectionStore } from "@/stores/connectionStore";
|
||||||
import { useQueryStore } from "@/stores/queryStore";
|
import { useQueryStore } from "@/stores/queryStore";
|
||||||
import { useSettingsStore } from "@/stores/settingsStore";
|
import { useSettingsStore } from "@/stores/settingsStore";
|
||||||
@@ -115,6 +116,7 @@ const setupRequired = ref(false);
|
|||||||
|
|
||||||
const showConnectionDialog = ref(false);
|
const showConnectionDialog = ref(false);
|
||||||
const connectionDialogPrefill = ref<ConnectionDeepLinkDraft | null>(null);
|
const connectionDialogPrefill = ref<ConnectionDeepLinkDraft | null>(null);
|
||||||
|
const connectionDialogInitialTab = ref<ConfigTab | undefined>(undefined);
|
||||||
const showSettingsDialog = ref(false);
|
const showSettingsDialog = ref(false);
|
||||||
const settingsInitialTab = ref("editor");
|
const settingsInitialTab = ref("editor");
|
||||||
const settingsInitialSection = ref<string | undefined>(undefined);
|
const settingsInitialSection = ref<string | undefined>(undefined);
|
||||||
@@ -798,7 +800,17 @@ async function openPendingConnectionLinks() {
|
|||||||
|
|
||||||
function setConnectionDialogOpen(value: boolean) {
|
function setConnectionDialogOpen(value: boolean) {
|
||||||
showConnectionDialog.value = value;
|
showConnectionDialog.value = value;
|
||||||
if (!value) connectionDialogPrefill.value = null;
|
if (!value) {
|
||||||
|
connectionDialogPrefill.value = null;
|
||||||
|
connectionDialogInitialTab.value = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openConnectionSettings(connectionId: string, initialTab: ConfigTab = "connection") {
|
||||||
|
if (!connectionStore.getConfig(connectionId)) return;
|
||||||
|
connectionDialogInitialTab.value = initialTab;
|
||||||
|
connectionStore.startEditing(connectionId);
|
||||||
|
showConnectionDialog.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function newQuery() {
|
async function newQuery() {
|
||||||
@@ -1638,6 +1650,7 @@ onUnmounted(() => {
|
|||||||
"
|
"
|
||||||
@structure-editor-close="activeTab && queryStore.closeTab(activeTab.id)"
|
@structure-editor-close="activeTab && queryStore.closeTab(activeTab.id)"
|
||||||
@open-settings="openSettings"
|
@open-settings="openSettings"
|
||||||
|
@open-connection-settings="openConnectionSettings"
|
||||||
/>
|
/>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</div>
|
</div>
|
||||||
@@ -1683,6 +1696,7 @@ onUnmounted(() => {
|
|||||||
<AppDialogs
|
<AppDialogs
|
||||||
:show-connection-dialog="showConnectionDialog"
|
:show-connection-dialog="showConnectionDialog"
|
||||||
:connection-prefill="connectionDialogPrefill"
|
:connection-prefill="connectionDialogPrefill"
|
||||||
|
:connection-initial-tab="connectionDialogInitialTab"
|
||||||
:show-settings-dialog="showSettingsDialog"
|
:show-settings-dialog="showSettingsDialog"
|
||||||
:settings-initial-tab="settingsInitialTab"
|
:settings-initial-tab="settingsInitialTab"
|
||||||
:settings-initial-section="settingsInitialSection"
|
:settings-initial-section="settingsInitialSection"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ type DbOption = { value: string; label: string };
|
|||||||
type DbCategory = { key: string; title: string; options: DbOption[] };
|
type DbCategory = { key: string; title: string; options: DbOption[] };
|
||||||
type DialogStep = "select" | "config";
|
type DialogStep = "select" | "config";
|
||||||
type DbPickerView = "icon" | "list";
|
type DbPickerView = "icon" | "list";
|
||||||
type ConfigTab = "connection" | "advanced" | "tls" | "transport";
|
export type ConfigTab = "connection" | "advanced" | "tls" | "transport";
|
||||||
type MqTokenSigningMode = "none" | "hs256" | "rs256";
|
type MqTokenSigningMode = "none" | "hs256" | "rs256";
|
||||||
type NacosAuthKind = NacosAuthConfig["kind"];
|
type NacosAuthKind = NacosAuthConfig["kind"];
|
||||||
type DremioConnectionMode = "arrow-flight-sql" | "legacy";
|
type DremioConnectionMode = "arrow-flight-sql" | "legacy";
|
||||||
@@ -97,6 +97,7 @@ const isDesktop = isTauriRuntime();
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
editConfig?: ConnectionConfig;
|
editConfig?: ConnectionConfig;
|
||||||
prefillConfig?: ConnectionDeepLinkDraft | null;
|
prefillConfig?: ConnectionDeepLinkDraft | null;
|
||||||
|
initialTab?: ConfigTab;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -125,6 +126,10 @@ const visibleSchemaInitialSelection = ref<string[]>([]);
|
|||||||
const visibleSchemaError = ref("");
|
const visibleSchemaError = ref("");
|
||||||
let testRunId = 0;
|
let testRunId = 0;
|
||||||
|
|
||||||
|
function initialConfigTab(): ConfigTab {
|
||||||
|
return props.initialTab ?? "connection";
|
||||||
|
}
|
||||||
|
|
||||||
const defaultForm = (): ConnectionForm => ({
|
const defaultForm = (): ConnectionForm => ({
|
||||||
name: "",
|
name: "",
|
||||||
db_type: "mysql",
|
db_type: "mysql",
|
||||||
@@ -1165,7 +1170,7 @@ watch(
|
|||||||
jdbcManualClasspathOpen.value = config.db_type === "prestosql" || (config.jdbc_driver_paths || []).length > 0;
|
jdbcManualClasspathOpen.value = config.db_type === "prestosql" || (config.jdbc_driver_paths || []).length > 0;
|
||||||
customDriverName.value = isCustomCompatibleProfile() ? config.driver_label || "" : "";
|
customDriverName.value = isCustomCompatibleProfile() ? config.driver_label || "" : "";
|
||||||
dialogStep.value = "config";
|
dialogStep.value = "config";
|
||||||
configTab.value = "connection";
|
configTab.value = initialConfigTab();
|
||||||
} else {
|
} else {
|
||||||
editingId.value = null;
|
editingId.value = null;
|
||||||
form.value = defaultForm();
|
form.value = defaultForm();
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ const DataGenerateDialog = defineAsyncComponent(() => import("@/components/gener
|
|||||||
import { useConnectionStore } from "@/stores/connectionStore";
|
import { useConnectionStore } from "@/stores/connectionStore";
|
||||||
import { useDialogSources } from "@/composables/useDialogSources";
|
import { useDialogSources } from "@/composables/useDialogSources";
|
||||||
import type { ConnectionDeepLinkDraft } from "@/lib/connectionDeepLink";
|
import type { ConnectionDeepLinkDraft } from "@/lib/connectionDeepLink";
|
||||||
|
import type { ConfigTab } from "@/components/connection/ConnectionDialog.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
showConnectionDialog: boolean;
|
showConnectionDialog: boolean;
|
||||||
connectionPrefill?: ConnectionDeepLinkDraft | null;
|
connectionPrefill?: ConnectionDeepLinkDraft | null;
|
||||||
|
connectionInitialTab?: ConfigTab;
|
||||||
showSettingsDialog: boolean;
|
showSettingsDialog: boolean;
|
||||||
settingsInitialTab?: string;
|
settingsInitialTab?: string;
|
||||||
settingsInitialSection?: string;
|
settingsInitialSection?: string;
|
||||||
@@ -108,6 +110,7 @@ watch(
|
|||||||
:open="shouldShowConnectionDialog"
|
:open="shouldShowConnectionDialog"
|
||||||
:edit-config="editConfig"
|
:edit-config="editConfig"
|
||||||
:prefill-config="connectionPrefill"
|
:prefill-config="connectionPrefill"
|
||||||
|
:initial-tab="connectionInitialTab"
|
||||||
@update:open="emit('update:showConnectionDialog', $event)"
|
@update:open="emit('update:showConnectionDialog', $event)"
|
||||||
@connect-started="emit('connectStarted', $event)"
|
@connect-started="emit('connectStarted', $event)"
|
||||||
@connect-succeeded="emit('connectSucceeded', $event)"
|
@connect-succeeded="emit('connectSucceeded', $event)"
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ const emit = defineEmits<{
|
|||||||
structureEditorSaved: [commentChanged: boolean];
|
structureEditorSaved: [commentChanged: boolean];
|
||||||
structureEditorClose: [];
|
structureEditorClose: [];
|
||||||
openSettings: [initialTab?: string, initialSection?: string];
|
openSettings: [initialTab?: string, initialSection?: string];
|
||||||
|
openConnectionSettings: [connectionId: string, initialTab: "advanced"];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -178,6 +179,11 @@ const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridR
|
|||||||
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
|
const tableFontSize = computed(() => settingsStore.editorSettings.tableFontSize);
|
||||||
const dataGridViewOptionsActive = computed(() => dataGridRef.value?.nullColumnsHidden || dataGridRef.value?.multiRowTranspose || dataGridRenderMode.value === "dom" || tableFontSize.value !== TABLE_FONT_SIZE_DEFAULT);
|
const dataGridViewOptionsActive = computed(() => dataGridRef.value?.nullColumnsHidden || dataGridRef.value?.multiRowTranspose || dataGridRenderMode.value === "dom" || tableFontSize.value !== TABLE_FONT_SIZE_DEFAULT);
|
||||||
const redisKeyBrowserRef = ref<SearchableBrowserHandle>();
|
const redisKeyBrowserRef = ref<SearchableBrowserHandle>();
|
||||||
|
|
||||||
|
function isQueryTimeoutError(message: string): boolean {
|
||||||
|
const lower = message.toLowerCase();
|
||||||
|
return lower.includes("query timed out") || lower.includes("查询超时");
|
||||||
|
}
|
||||||
const etcdKeyBrowserRef = ref<SearchableBrowserHandle>();
|
const etcdKeyBrowserRef = ref<SearchableBrowserHandle>();
|
||||||
const zookeeperKeyBrowserRef = ref<SearchableBrowserHandle>();
|
const zookeeperKeyBrowserRef = ref<SearchableBrowserHandle>();
|
||||||
const objectBrowserRef = ref<SearchableBrowserHandle>();
|
const objectBrowserRef = ref<SearchableBrowserHandle>();
|
||||||
@@ -977,6 +983,10 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
|||||||
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string, mode?: DataGridSortMode) => emit('sort', column, columnIndex, direction, whereInput, mode)"
|
@sort="(column: string, columnIndex: number, direction: 'asc' | 'desc' | null, whereInput?: string, mode?: DataGridSortMode) => emit('sort', column, columnIndex, direction, whereInput, mode)"
|
||||||
>
|
>
|
||||||
<template v-if="activeTab.result?.columns.includes('Error')" #error-actions="{ errorMessage }">
|
<template v-if="activeTab.result?.columns.includes('Error')" #error-actions="{ errorMessage }">
|
||||||
|
<Button v-if="activeTab.connectionId && isQueryTimeoutError(String(errorMessage))" variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('openConnectionSettings', activeTab.connectionId, 'advanced')">
|
||||||
|
<Wrench class="h-3.5 w-3.5" />
|
||||||
|
{{ t("editor.changeQueryTimeout") }}
|
||||||
|
</Button>
|
||||||
<Button variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('fixWithAi', String(errorMessage))">
|
<Button variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('fixWithAi', String(errorMessage))">
|
||||||
<Bot class="h-3.5 w-3.5" />
|
<Bot class="h-3.5 w-3.5" />
|
||||||
{{ t("ai.fixWithAi") }}
|
{{ t("ai.fixWithAi") }}
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ export default {
|
|||||||
pressToExecute: "Press {mod}+Enter to execute",
|
pressToExecute: "Press {mod}+Enter to execute",
|
||||||
pressToSaveSql: "Press {mod}+S to save SQL",
|
pressToSaveSql: "Press {mod}+S to save SQL",
|
||||||
queryTimeoutError: "Query timed out ({seconds}s). Check whether the database connection is healthy.",
|
queryTimeoutError: "Query timed out ({seconds}s). Check whether the database connection is healthy.",
|
||||||
|
changeQueryTimeout: "Change query timeout",
|
||||||
connectionMayBeLost: "The connection may have been lost. Refresh data and try again.",
|
connectionMayBeLost: "The connection may have been lost. Refresh data and try again.",
|
||||||
showResultsPane: "Show results",
|
showResultsPane: "Show results",
|
||||||
hideResultsPane: "Hide results",
|
hideResultsPane: "Hide results",
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ export default withEnglishFallback({
|
|||||||
pressToExecute: "按 {mod}+Enter 执行查询",
|
pressToExecute: "按 {mod}+Enter 执行查询",
|
||||||
pressToSaveSql: "按 {mod}+S 保存 SQL",
|
pressToSaveSql: "按 {mod}+S 保存 SQL",
|
||||||
queryTimeoutError: "查询超时 ({seconds}s),请检查数据库连接是否正常",
|
queryTimeoutError: "查询超时 ({seconds}s),请检查数据库连接是否正常",
|
||||||
|
changeQueryTimeout: "修改查询超时时间",
|
||||||
connectionMayBeLost: "连接可能已断开,请刷新数据重试",
|
connectionMayBeLost: "连接可能已断开,请刷新数据重试",
|
||||||
showResultsPane: "显示结果",
|
showResultsPane: "显示结果",
|
||||||
hideResultsPane: "收起结果",
|
hideResultsPane: "收起结果",
|
||||||
|
|||||||
Reference in new issue
Block a user