From 61dab6a39abf54d44c1f2baa7cf032a13dde5969 Mon Sep 17 00:00:00 2001 From: xuans Date: Sat, 26 Sep 2026 23:15:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=82=AE=E7=AE=B1=E5=90=8E?= =?UTF-8?q?=E7=BC=80=E6=88=AA=E6=96=AD=E5=B9=B6=E4=BC=98=E5=8C=96DNS?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=B8=80=E5=B1=8F=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/SetupWizard/DNSSetup.css | 144 ++++++++++++++++++ .../src/views/SetupWizard/SetupWizard.css | 4 +- .../src/views/SetupWizard/SetupWizard.vue | 51 +++---- .../views/SetupWizard/SetupWizardLayout.css | 2 +- .../SetupWizard/SetupWizardLayout.test.js | 37 +++++ 5 files changed, 205 insertions(+), 33 deletions(-) create mode 100644 frontend/src/views/SetupWizard/DNSSetup.css diff --git a/frontend/src/views/SetupWizard/DNSSetup.css b/frontend/src/views/SetupWizard/DNSSetup.css new file mode 100644 index 0000000..b1eed05 --- /dev/null +++ b/frontend/src/views/SetupWizard/DNSSetup.css @@ -0,0 +1,144 @@ +.setup-dns-step .dns-settings-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px 14px; +} + +.setup-dns-step .dns-settings-grid label { + margin-top: 0; +} + +.setup-dns-step .dns-provider-status { + display: flex; + align-items: center; + gap: 6px; + margin: 10px 0 0; + color: #24734b; + font-size: 12px; +} + +.setup-dns-step .dns-provider-status.unavailable { + color: #996d16; +} + +.setup-dns-step .credential-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px 14px; +} + +.setup-dns-step .credential-visibility-row { + margin-top: 10px; + padding: 8px 10px; + font-size: 12px; +} + +.setup-dns-step .credential-visibility-control { + margin: 0; + font-size: 12px; +} + +.setup-dns-step .credential-visibility-control input { + flex: 0 0 16px; + width: 16px; + height: 16px; + min-height: 16px; + margin: 0; + padding: 0; +} + +.setup-dns-step .credential-grid > label:has(textarea) { + grid-column: 1 / -1; +} + +.setup-dns-step .dns-test-actions { + gap: 8px; + margin: 12px 0; +} + +.setup-dns-step .dns-test-button { + min-width: 132px; + min-height: 36px; + font-size: 12px; +} + +.setup-dns-step .dns-verification-progress, +.setup-dns-step .dns-verification-success { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px 12px; + margin-top: 8px; + padding: 9px 12px; + font-size: 12px; + line-height: 1.5; +} + +.setup-dns-step .dns-verification-progress strong, +.setup-dns-step .dns-verification-success strong { + font-size: 12px; +} + +.setup-dns-step .dns-verification-report { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + margin-top: 10px; + padding: 10px; +} + +.setup-dns-step .dns-report-heading { + grid-column: 1 / -1; + justify-content: flex-start; + align-items: center; + gap: 6px; +} + +.setup-dns-step .dns-report-heading strong { + font-size: 12px; +} + +.setup-dns-step .dns-verification-stage { + grid-template-columns: minmax(0, 1fr) auto auto; + gap: 6px; + min-width: 0; + padding: 9px; + font-size: 12px; +} + +.setup-dns-step .dns-verification-stage strong { + font-size: 12px; +} + +.setup-dns-step .dns-verification-stage small { + grid-column: 1 / -1; + overflow: visible; + white-space: normal; + overflow-wrap: anywhere; + font-size: 12px; + line-height: 1.5; +} + +.setup-dns-step .inline-error { + margin-top: 8px; + font-size: 12px; + overflow-wrap: anywhere; +} + +@media (min-width: 1201px) { + .setup-dns-step .dns-settings-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} + +@media (max-width: 900px) { + .setup-dns-step .credential-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 600px) { + .setup-dns-step .dns-settings-grid, + .setup-dns-step .credential-grid, + .setup-dns-step .dns-verification-report { + grid-template-columns: minmax(0, 1fr); + } +} diff --git a/frontend/src/views/SetupWizard/SetupWizard.css b/frontend/src/views/SetupWizard/SetupWizard.css index 48b4828..a0deef4 100644 --- a/frontend/src/views/SetupWizard/SetupWizard.css +++ b/frontend/src/views/SetupWizard/SetupWizard.css @@ -286,7 +286,7 @@ label > small { .email-input-group { min-width: 0; display: grid; - grid-template-columns: minmax(0, 1fr) minmax(88px, 112px); + grid-template-columns: minmax(0, 1fr) 148px; gap: 6px; position: relative; } @@ -1014,7 +1014,7 @@ button:disabled { } .email-input-group { - grid-template-columns: minmax(0, 1fr) minmax(78px, 96px); + grid-template-columns: minmax(0, 1fr) 140px; gap: 5px; } diff --git a/frontend/src/views/SetupWizard/SetupWizard.vue b/frontend/src/views/SetupWizard/SetupWizard.vue index 7b6f6e1..e7b6650 100644 --- a/frontend/src/views/SetupWizard/SetupWizard.vue +++ b/frontend/src/views/SetupWizard/SetupWizard.vue @@ -510,9 +510,9 @@ const { -
+
03DNS 验证 -
+
-

- 阿里云 RAM 权限验证最多等待 6 秒:系统会创建、查询并清理临时 TXT - 记录。以上 300 秒和 5 秒用于实际申请证书时的公网 DNS-01 - 传播等待与轮询。 -

{{ dnsCatalogError }}

{{ @@ -605,7 +598,7 @@ const { ? "在线验证可用" : "当前仅提供字段模型" }} - {{ selectedDNSProvider.description }} + {{ selectedDNSProvider.description }}
{{ dnsTesting - ? "正在创建、查询并清理测试记录……" + ? "正在验证……" : "测试 DNS API" }} - 测试会临时创建 DNS-01 TXT - 记录并自动清理,明文凭据不会写入普通配置文件。 + + 测试会创建、查询并清理临时 TXT 记录,验证 DNS API 操作权限,不等待公网传播。阿里云验证最多等待 6 秒;明文凭据不会写入普通配置文件。 +
- - 正在通过阿里云 DNS API 创建、查询并清理临时 TXT 记录,不等待公网 DNS 传播,通常数秒即可完成;实际申请证书时,仍可能需要等待公网 DNS-01 记录传播。 - - - 系统正在创建临时 TXT、查询验证记录并自动清理。这是 DNS API 权限验证;实际申请证书时,仍可能需要等待公网 DNS-01 记录传播。 -

{{ dnsTestError }}

DNS API 在线验证通过 凭据已加密保存,本次验证结果有效至 + >有效至 {{ formatVerificationExpiry(dnsVerification.expires_at) - }}。修改服务商、测试域名或凭据后需要重新测试。 + + 凭据已加密保存。修改服务商、测试域名或凭据后需要重新测试,验证过期后也必须重新验证。 +
在线测试过程 - + 临时记录:{{ dnsVerification.test_report.record_name }} - +
{{ stage.name }} {{ formatVerificationStageStatus(stage.status) }} - {{ stage.message }} + {{ stage.message }} + {{ stage.message }}
@@ -840,4 +830,5 @@ const { + diff --git a/frontend/src/views/SetupWizard/SetupWizardLayout.css b/frontend/src/views/SetupWizard/SetupWizardLayout.css index ddf2cc2..676fb17 100644 --- a/frontend/src/views/SetupWizard/SetupWizardLayout.css +++ b/frontend/src/views/SetupWizard/SetupWizardLayout.css @@ -156,7 +156,7 @@ } .access-shell--setup .email-input-group { - grid-template-columns: minmax(0, 1fr) 96px; + grid-template-columns: minmax(0, 1fr) 148px; } .access-shell--setup .service-access-grid { diff --git a/frontend/src/views/SetupWizard/SetupWizardLayout.test.js b/frontend/src/views/SetupWizard/SetupWizardLayout.test.js index 88de302..70d20d1 100644 --- a/frontend/src/views/SetupWizard/SetupWizardLayout.test.js +++ b/frontend/src/views/SetupWizard/SetupWizardLayout.test.js @@ -22,6 +22,43 @@ function hasClass(name) { && prop.value?.content.split(/\s+/).includes(name)); } +test("email suffix retains enough width in base and compact layouts", () => { + for (const name of ["./SetupWizard.css", "./SetupWizardLayout.css"]) { + const css = readFileSync(new URL(name, import.meta.url), "utf8"); + const rules = [...css.matchAll(/\.email-input-group\s*\{([^}]+)\}/g)]; + assert.ok(rules.length > 0); + for (const [, body] of rules) { + const width = body.match(/grid-template-columns:\s*minmax\(0, 1fr\)\s+(\d+)px/); + assert.ok(width, name); + assert.ok(Number(width[1]) >= 140, name); + } + } +}); + +test("DNS settings share a compact grid without removing verification controls", () => { + const step = find(template("./SetupWizard.vue"), hasClass("setup-dns-step")); + assert.ok(step); + const grid = find(step, hasClass("dns-settings-grid")); + assert.ok(grid); + for (const id of ["dns-provider", "dns-test-domain", "propagation-timeout-secs", "propagation-polling-interval-secs"]) { + assert.ok(find(grid, (node) => node.props?.some((prop) => + prop.name === "id" && prop.value?.content === id)), id); + } + assert.ok(find(step, hasClass("dns-test-button"))); + assert.ok(find(step, hasClass("dns-verification-report"))); +}); + +test("DNS stage explanations use tooltips only for successful stages", () => { + const stage = find(template("./SetupWizard.vue"), hasClass("dns-verification-stage")); + const tip = find(stage, (node) => node.tag === "HelpTip"); + assert.equal(tip.props.find((prop) => prop.name === "if").exp.content, "stage.status === 'completed'"); + const message = find(stage, (node) => node.tag === "small"); + assert.ok(message.props.some((prop) => prop.name === "else")); + const css = readFileSync(new URL("./DNSSetup.css", import.meta.url), "utf8"); + assert.match(css, /\.dns-verification-stage small\s*\{[^}]*white-space:\s*normal/); + assert.match(css, /\.dns-verification-stage small\s*\{[^}]*overflow-wrap:\s*anywhere/); +}); + test("certificate root remains editable during bootstrap", () => { const root = template("./SetupWizard.vue"); const input = find(root, (node) => node.props?.some((prop) =>