From a9bc68cd28d9dff4e40aa236ced75242608f97fa Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 26 Oct 2026 11:40:11 +0800 Subject: [PATCH] fix(frontend): polish cert dialog and wire upload API Prefer drag-and-drop for crt/key with PEM paste collapsed; rename primary actions; add HTTP-01 prechecks. Upload posts to POST /system/tls/certificate with cert_source from status. --- frontend/src/locales/en-US.json | 8 ++- frontend/src/locales/zh-CN.json | 8 ++- .../settings/components/GatewaySettings.vue | 65 ++++++++++++++++--- 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index a90abad..fc510b3 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -972,7 +972,13 @@ "http01Hint": "Let’s Encrypt HTTP-01. Port 80 must be reachable. Auto-renewal status appears in the list.", "certKeyRequired": "Certificate and private key are required", "certUploaded": "Certificate uploaded", - "uploadApiPending": "Upload API is not ready yet (POST /system/tls/certificate). Use HTTP-01 for now." + "uploadApiPending": "Upload API is not ready yet (POST /system/tls/certificate). Use HTTP-01 for now.", + "dropHint": "Drop a file here, or click to choose", + "pastePem": "Or paste PEM text", + "importCert": "Import certificate", + "startIssue": "Start issuance", + "http01CheckDns": "DNS already points to this public entry", + "http01CheckPort": "Issuance port is reachable (usually 80, or matches entry port)" }, "feishuSync": { "title": "Feishu directory", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index 320607b..1b39ae5 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -972,7 +972,13 @@ "http01Hint": "使用 Let’s Encrypt HTTP-01 验证;需公网可访问 80 端口。过期前将尝试自动续期,失败时列表会显示状态。", "certKeyRequired": "请填写证书与私钥", "certUploaded": "证书已上传", - "uploadApiPending": "上传证书接口尚未就绪,请先由后端落地 POST /system/tls/certificate,或改用 HTTP-01 申请。" + "uploadApiPending": "上传证书接口尚未就绪,请先由后端落地 POST /system/tls/certificate,或改用 HTTP-01 申请。", + "dropHint": "拖拽文件到此处,或点击选择", + "pastePem": "或粘贴 PEM 文本", + "importCert": "导入证书", + "startIssue": "开始申请", + "http01CheckDns": "DNS 已指向本机公网入口", + "http01CheckPort": "申请用端口可达(通常为 80,或与入口配置一致)" }, "feishuSync": { "title": "飞书组织与成员", diff --git a/frontend/src/views/settings/components/GatewaySettings.vue b/frontend/src/views/settings/components/GatewaySettings.vue index e02e1ca..c71bad5 100644 --- a/frontend/src/views/settings/components/GatewaySettings.vue +++ b/frontend/src/views/settings/components/GatewaySettings.vue @@ -138,16 +138,42 @@ @@ -160,13 +186,19 @@ - + +
    +
  • {{ $t('tls.http01CheckDns') }}
  • +
  • {{ $t('tls.http01CheckPort') }}
  • +
{{ nginxActivateLog }}
@@ -207,6 +239,8 @@ const certForm = reactive({ method: 'upload', certPem: '', keyPem: '', + certFileName: '', + keyFileName: '', host: '', email: '', }) @@ -243,6 +277,8 @@ function resetCertForm() { certForm.method = 'upload' certForm.certPem = '' certForm.keyPem = '' + certForm.certFileName = '' + certForm.keyFileName = '' certForm.host = entry.host certForm.email = '' nginxActivateLog.value = '' @@ -255,7 +291,11 @@ function openAddCert() { function readPemFile(file, field) { const reader = new FileReader() - reader.onload = () => { certForm[field] = String(reader.result || '') } + reader.onload = () => { + certForm[field] = String(reader.result || '') + if (field === 'certPem') certForm.certFileName = file.name + if (field === 'keyPem') certForm.keyFileName = file.name + } reader.readAsText(file) return false } @@ -461,5 +501,10 @@ onMounted(() => { if (!auth.mustChange) refreshAll() }) transition: border-color .15s, box-shadow .15s; } .method-card.active { border-color: var(--el-color-primary); box-shadow: 0 0 0 1px var(--el-color-primary) inset; } -.upload-btn { color: var(--el-color-primary); border-style: dashed; } +.pem-drop { width: 100%; } +.pem-drop :deep(.el-upload), .pem-drop :deep(.el-upload-dragger) { width: 100%; } +.pem-drop-inner { padding: 8px 0; } +.pem-drop-title { color: var(--el-color-primary); font-weight: 600; } +.pem-drop-hint { margin-top: 4px; font-size: 12px; color: var(--text-secondary); } +.http01-checklist { margin: 0; padding-left: 1.2em; color: var(--text-secondary); font-size: 13px; line-height: 1.7; }