修复托管域名配置误关闭和泛域名校验提示

移除域名配置弹窗背景点击关闭,避免鼠标选择输入内容时误关闭;补充泛域名格式提示和前端校验,新增回归测试。
This commit is contained in:
xuans 2026-10-16 01:51:15 +08:00
parent 225388bf3f
commit 7167d0de78
5 changed files with 60 additions and 3 deletions

View File

@ -149,6 +149,14 @@ export function useDomainForm({ fetchAdmin, domains, servers, domainServers, not
formError.value = "请输入主域名";
return;
}
if (payload.certificate_type === "wildcard" && !payload.name.trim().startsWith("*.")) {
formError.value = "泛域名主域名必须以 *. 开头,例如 *.example.com";
return;
}
if (payload.certificate_type !== "wildcard" && payload.name.trim().startsWith("*.")) {
formError.value = "只有泛域名证书类型允许使用 *. 域名";
return;
}
if (payload.certificate_type === "san" && payload.sans.length === 0) {
formError.value = "SAN 证书至少需要填写一个附加域名";
return;

View File

@ -67,6 +67,24 @@ test("HTTP 验证拒绝主泛域名和附加泛域名,不提交请求", async
assert.equal(calls, 0);
});
test("泛域名必须填写带通配符的主域名,不提交无效配置", async (t) => {
let calls = 0;
const { state } = await mountForm(t, async () => {
calls += 1;
return Response.json({});
});
await startCreate(state);
state.form.value.certificate_type = "wildcard";
state.form.value.name = "pcux.cn";
await state.saveDomain();
assert.equal(calls, 0);
assert.match(state.formError.value, /泛域名主域名必须以 \*\. 开头/);
state.form.value.name = "*.pcux.cn";
await state.saveDomain();
assert.equal(calls, 1);
});
test("编辑时保留已有 HTTP 验证方式", async (t) => {
const { state } = await mountForm(t, async () => Response.json({ items: [] }));
await state.openEdit({ ...firstDomain, challenge_type: "http-01" });

View File

@ -68,6 +68,13 @@
gap: 6px;
}
.domain-modal .field-hint {
margin-top: -1px;
color: #6d7f98;
font-size: 12px;
line-height: 1.45;
}
.domain-modal .switch-field {
align-items: center;
margin: 4px 0 10px;

View File

@ -67,6 +67,10 @@ async function renderModal(overrides = {}) {
return html;
}
async function readModalSource() {
return readFile(new URL("./DomainModal.vue", import.meta.url), "utf8");
}
test("域名表单使用复选框同时显示两台已关联服务器并提供复用提示", async () => {
const html = await renderModal();
const inputs = html.match(/<input\b[^>]*>/g) || [];
@ -81,6 +85,22 @@ test("域名表单使用复选框同时显示两台已关联服务器并提供
assert.match(html, /当前域名所属项目/);
});
test("域名表单不会通过背景点击误关闭,并提示泛域名格式", async () => {
const source = await readModalSource();
const html = await renderModal({ form: {
name: "pcux.cn",
certificate_type: "wildcard",
sans: "",
auto_renew: false,
acme_environment: "production",
dns_provider: "aliyun",
server_ids: [],
} });
assert.doesNotMatch(source, /class="modal-backdrop domain-backdrop"[^>]*@click/);
assert.match(html, /placeholder="\*\.example\.com"/);
assert.match(html, /泛域名必须以 \*\. 开头/);
});
test("域名账户显示归属与服务商,原绑定不可用不被静默清空", async () => {
const html = await renderModal({
dnsAccountID: "old-account", dnsBound: true, dnsUnavailableSelection: true,

View File

@ -30,7 +30,7 @@ const {
</script>
<template>
<div v-if="showForm" class="modal-backdrop domain-backdrop" @click.self="closeForm">
<div v-if="showForm" class="modal-backdrop domain-backdrop">
<section
class="modal-card domain-modal"
role="dialog"
@ -61,9 +61,13 @@ const {
v-model="form.name"
:disabled="saving || domainSaveUncertain"
type="text"
placeholder="例如 example.com"
:placeholder="form.certificate_type === 'wildcard' ? '*.example.com' : '例如 example.com'"
autocomplete="off"
/></label>
/><small
v-if="form.certificate_type === 'wildcard'"
class="field-hint"
>泛域名必须以 *. 开头,例如 *.example.com;不会自动包含根域名。</small
></label>
<label class="field" for="certificate-type"
><span>证书类型</span
><select