From 7a138559dec986884404fca09f3958edd2ed3d11 Mon Sep 17 00:00:00 2001 From: sans Date: Sat, 18 Jul 2026 23:51:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84ui/=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/main.py | 3 +- backend/routers/admin.py | 50 +++++++++++--- frontend/src/api/index.js | 4 ++ frontend/src/views/Domains.vue | 119 ++++++++++++++++++++++++++++++--- 4 files changed, 155 insertions(+), 21 deletions(-) diff --git a/backend/main.py b/backend/main.py index 70d200c..fec0dc8 100644 --- a/backend/main.py +++ b/backend/main.py @@ -19,7 +19,7 @@ from backend.routers.admin import ( list_logs, list_acme_configs, get_acme_config, create_acme_config, update_acme_config, delete_acme_config, issue_cert, renew_cert, auto_renew_all, list_acme_logs, get_cert_info, - download_cert_file, admin_generate_script, + download_cert_file, admin_generate_script, admin_download_script, ) logging.basicConfig(level=logging.DEBUG) @@ -94,6 +94,7 @@ app.get("/admin/api/acme/logs")(list_acme_logs) app.get("/admin/api/cert-info/{domain_id}")(get_cert_info) app.get("/admin/api/cert-download/{domain_id}/{file_type}")(download_cert_file) app.get("/admin/api/script")(admin_generate_script) +app.get("/admin/api/script/download")(admin_download_script) logger.info("=== 路由注册完成 ===") for route in app.routes: diff --git a/backend/routers/admin.py b/backend/routers/admin.py index 0268c9d..2ba1d5d 100644 --- a/backend/routers/admin.py +++ b/backend/routers/admin.py @@ -582,15 +582,8 @@ async def list_acme_logs(status: str | None = None, db: AsyncSession = Depends(g # ──────────────── 部署脚本 ──────────────── -@router.get("/script") -async def admin_generate_script( - domain: str, - server_name: str, - os: str = "linux", - db: AsyncSession = Depends(get_db), - _: bool = Depends(require_auth), -): - """管理端生成部署脚本""" +async def _render_script(domain: str, server_name: str, os: str, db: AsyncSession) -> tuple[str, Server, Domain]: + """渲染部署脚本,返回 (script, server, domain_obj)""" from jinja2 import Environment, FileSystemLoader template_dir = Path(__file__).parent.parent / "templates_cert" @@ -619,7 +612,44 @@ async def admin_generate_script( check_cmd=d.check_cmd, reload_cmd=d.reload_cmd, ) - return {"script": script} + return script, server, d + + +@router.get("/script") +async def admin_generate_script( + domain: str, + server_name: str, + os: str = "linux", + db: AsyncSession = Depends(get_db), + _: bool = Depends(require_auth), +): + """管理端生成部署脚本(JSON)""" + script, server, d = await _render_script(domain, server_name, os, db) + return { + "script": script, + "token": server.token, + "cert_dir": d.cert_dir, + "check_cmd": d.check_cmd, + "reload_cmd": d.reload_cmd, + } + + +@router.get("/script/download") +async def admin_download_script( + domain: str, + server_name: str, + os: str = "linux", + db: AsyncSession = Depends(get_db), + _: bool = Depends(require_auth), +): + """下载脚本文件(纯文本,供 curl 使用)""" + script, _, _ = await _render_script(domain, server_name, os, db) + ext = "ps1" if os == "windows" else "sh" + filename = f"deploy-{domain.replace('*', '_')}.{ext}" + return PlainTextResponse( + script, + headers={"Content-Disposition": f'attachment; filename="{filename}"'}, + ) # ──────────────── 证书信息 ──────────────── diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index a73c063..dff0818 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -47,6 +47,10 @@ export const deleteDomain = (id) => api.delete(`/domains/${id}`) // Logs export const getLogs = (status) => api.get('/logs', { params: { status } }) +// ACME +export const issueCert = (domainId) => api.post(`/acme/issue/${domainId}`) +export const renewCert = (domainId) => api.post(`/acme/renew/${domainId}`) + // Script (通过管理接口获取脚本内容) export const getScript = (domain, serverName) => axios.get('/api/script', { params: { domain, server_name: serverName } }) diff --git a/frontend/src/views/Domains.vue b/frontend/src/views/Domains.vue index 17a0e39..af6f93b 100644 --- a/frontend/src/views/Domains.vue +++ b/frontend/src/views/Domains.vue @@ -41,10 +41,11 @@ - +