Feature:支持 SQL Server 旧版兼容模式 (#2181)
* fix: 支持 SQL Server 旧版非加密重试 * fix: 优化 SQL Server 旧版兼容模式入口 --------- Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
1 parent
8747a0e8f9
commit
d04463ebeb
7 files changed
+136
-14
No files matched your search
@@ -867,6 +867,28 @@ function connectionErrorWithDriverUpdateHint(config: ConnectionConfig, message:
|
||||
return appendAgentDriverUpdateHint(message, t("connection.agentDriverUpdateConnectionHint"));
|
||||
}
|
||||
|
||||
function isSqlServerLegacyUnencryptedMode(params: string | undefined): boolean {
|
||||
const normalized = (params || "").trim().replace(/^\?/, "").replace(/;/g, "&");
|
||||
if (!normalized) return false;
|
||||
const parsed = new URLSearchParams(normalized);
|
||||
for (const [key, value] of parsed.entries()) {
|
||||
if (key.trim().toLowerCase() === "sqlserverencryption") {
|
||||
return ["disabled", "disable", "false", "0", "off"].includes(value.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setSqlServerLegacyUnencryptedMode(params: string | undefined, enabled: boolean): string {
|
||||
const normalized = (params || "").trim().replace(/^\?/, "").replace(/;/g, "&");
|
||||
return setUrlParam(normalized, "sqlserverEncryption", enabled ? "disabled" : "");
|
||||
}
|
||||
|
||||
function isSqlServerTlsHandshakeFailure(message: string): boolean {
|
||||
const text = message.toLowerCase();
|
||||
return text.includes("sql server") && text.includes("tls") && (text.includes("handshake") || text.includes("eof") || text.includes("performing i/o"));
|
||||
}
|
||||
|
||||
async function testConnectionWithTimeout(config: ConnectionConfig, runId: number): Promise<string> {
|
||||
const timeoutMs = connectionAttemptTimeoutMs(config);
|
||||
const timeoutMessage = connectionAttemptTimeoutMessage(timeoutMs);
|
||||
@@ -1608,6 +1630,13 @@ const testResultMessage = computed(() => {
|
||||
if (!testResult.value) return "";
|
||||
return testResult.value.ok ? t("connection.testSuccess") : translateBackendError(t, testResult.value.message);
|
||||
});
|
||||
const sqlServerLegacyUnencryptedModeEnabled = computed({
|
||||
get: () => form.value.db_type === "sqlserver" && isSqlServerLegacyUnencryptedMode(form.value.url_params),
|
||||
set: (enabled: boolean) => {
|
||||
if (form.value.db_type !== "sqlserver") return;
|
||||
form.value.url_params = setSqlServerLegacyUnencryptedMode(form.value.url_params, enabled);
|
||||
},
|
||||
});
|
||||
const shouldUseWideConnectionDialog = computed(() => dialogStep.value === "config" && (canChooseVisibleDatabases.value || (canChooseVisibleSchemas.value && !visibleFilterUsesSchemas.value)));
|
||||
const connectionDialogContentClass = computed(() => {
|
||||
if (dialogStep.value === "select") return "sm:max-w-[760px]";
|
||||
@@ -1685,6 +1714,10 @@ async function testConnection() {
|
||||
const message = connectionErrorWithDriverUpdateHint(config, mongodbAuthFailureHint(String(e)));
|
||||
const fallbackMessage = await tryNacosDockerConsoleFallback(config, message, runId);
|
||||
if (runId !== testRunId) return;
|
||||
const shouldShowSqlServerLegacyMode = !fallbackMessage && config.db_type === "sqlserver" && !isSqlServerLegacyUnencryptedMode(config.url_params) && isSqlServerTlsHandshakeFailure(message);
|
||||
if (shouldShowSqlServerLegacyMode) {
|
||||
configTab.value = "advanced";
|
||||
}
|
||||
testResult.value = fallbackMessage ? { ok: true, message: fallbackMessage } : { ok: false, message };
|
||||
} finally {
|
||||
if (runId === testRunId) {
|
||||
@@ -4297,6 +4330,18 @@ function openExternalUrl(url: string) {
|
||||
<span class="text-xs text-muted-foreground">{{ t("connection.readOnlyHint") }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-show="form.db_type === 'sqlserver'" class="grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.sqlServerLegacyUnencryptedMode") }}</Label>
|
||||
<div class="col-span-3 flex flex-col gap-1">
|
||||
<label class="flex h-5 cursor-pointer items-center gap-2">
|
||||
<input type="checkbox" v-model="sqlServerLegacyUnencryptedModeEnabled" class="mr-0" />
|
||||
<span class="text-xs text-foreground">{{ t("connection.sqlServerLegacyUnencryptedModeEnable") }}</span>
|
||||
</label>
|
||||
<p class="m-0 whitespace-pre-line text-xs leading-5 text-muted-foreground">
|
||||
{{ t("connection.sqlServerLegacyUnencryptedModeHint") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="form.db_type === 'redis'" class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("settings.redisScanPageSize") }}</Label>
|
||||
<div class="col-span-3 flex flex-col gap-1">
|
||||
@@ -4318,7 +4363,7 @@ function openExternalUrl(url: string) {
|
||||
|
||||
<TabsContent v-if="canUseTransportLayers" value="transport" class="m-0">
|
||||
<div class="connection-form-body grid gap-4 py-4 pr-2 max-h-[65vh] overflow-y-auto">
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<div class="connection-label-wide-grid grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelSmallPaddedClass">{{ t("connection.sshHops") }}</Label>
|
||||
<div class="col-span-3 grid gap-3">
|
||||
<div class="flex flex-wrap items-center gap-1 text-[11px] text-muted-foreground">
|
||||
@@ -4629,4 +4674,8 @@ function openExternalUrl(url: string) {
|
||||
width: min(100%, 36rem);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.connection-dialog-content .grid.grid-cols-4.connection-label-wide-grid {
|
||||
grid-template-columns: 7.75rem repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user