feat: redesign system page - service status with refresh, separate backup/restore cards

This commit is contained in:
tian 2026-05-06 16:17:44 +08:00
parent 80955c95a0
commit 3ddffdc8f4
2 changed files with 61 additions and 16 deletions

View File

@ -1,36 +1,33 @@
{{define "system"}}
<div class="card">
<div class="crumb">系统管理 / 系统状态</div>
<div class="muted small" style="margin-top:8px">系统状态页负责平台健康检查和数据备份恢复。</div>
</div>
<div class="detail-grid">
<div class="card">
<h2 class="title-with-icon">{{icon "heartbeat"}}<span>后台健康</span></h2>
<h2 class="title-with-icon">{{icon "heartbeat"}}<span>服务状态</span></h2>
<div class="info-list compact-list">
<div><span>健康检查</span><strong class="mono">/health</strong></div>
<div><span>接口文档</span><strong class="mono">/openapi.json</strong></div>
<div><span>管理后台</span><strong id="svc-status">检测中…</strong></div>
<div><span>接口文档</span><strong id="api-status">检测中…</strong></div>
</div>
<div class="actions" style="margin-top:12px">
<a class="btn ghost" href="/health">健康检查</a>
<a class="btn ghost" href="/openapi.json">OpenAPI</a>
<button class="btn ghost" type="button" id="btn-refresh">刷新</button>
</div>
</div>
</div>
<div class="detail-grid">
<div class="card">
<h2 class="title-with-icon">{{icon "audit"}}<span>数据备份 / 恢复</span></h2>
<h2 class="title-with-icon">{{icon "audit"}}<span>数据备份</span></h2>
<div class="info-list compact-list">
<div><span>数据库文件</span><strong class="mono">{{if .DBPath}}{{.DBPath}}{{else}}未配置{{end}}</strong></div>
<div><span>备份方式</span><strong>另存为数据库文件</strong></div>
</div>
<div class="actions" style="margin-top:12px">
<button type="button" class="btn ghost js-export-db" data-export-url="/ui/system/db-backup" data-default-filename="app.db">备份数据库</button>
</div>
<form method="post" action="/ui/system/db-restore" enctype="multipart/form-data" style="margin-top:12px">
</div>
<div class="card">
<h2 class="title-with-icon">{{icon "apply"}}<span>数据恢复</span></h2>
<form method="post" action="/ui/system/db-restore" enctype="multipart/form-data">
<div class="field-grid">
<label class="full"><span>恢复数据库</span><input type="file" name="file" accept=".db,application/octet-stream" required /></label>
<label class="full"><span>选择备份文件</span><input type="file" name="file" accept=".db,application/octet-stream" required /></label>
</div>
<div class="actions" style="margin-top:12px">
<button type="submit" class="secondary">恢复数据库</button>
@ -38,4 +35,52 @@
</form>
</div>
</div>
<script>
(function() {
var svcEl = document.getElementById("svc-status");
var apiEl = document.getElementById("api-status");
function check() {
svcEl.textContent = "检测中…";
svcEl.className = "";
apiEl.textContent = "检测中…";
apiEl.className = "";
fetch("/health")
.then(function(r) { return r.text(); })
.then(function(t) {
if (t.indexOf("ok") !== -1) {
svcEl.textContent = "运行正常";
svcEl.className = "ok";
} else {
svcEl.textContent = "异常";
svcEl.className = "bad";
}
})
.catch(function() {
svcEl.textContent = "无法连接";
svcEl.className = "bad";
});
fetch("/openapi.json")
.then(function(r) {
if (r.ok) {
apiEl.textContent = "正常";
apiEl.className = "ok";
} else {
apiEl.textContent = "异常 (" + r.status + ")";
apiEl.className = "bad";
}
})
.catch(function() {
apiEl.textContent = "无法连接";
apiEl.className = "bad";
});
}
document.getElementById("btn-refresh").addEventListener("click", check);
check();
})();
</script>
{{end}}

View File

@ -3414,7 +3414,7 @@ func TestUI_AuditAndSystemPagesDefineNewScopes(t *testing.T) {
rrSystem := httptest.NewRecorder()
ui.pageSystem(rrSystem, httptest.NewRequest(http.MethodGet, "/ui/system", nil))
for _, want := range []string{"系统管理 / 系统状态", "后台健康", "数据备份 / 恢复", "/health", "/openapi.json"} {
for _, want := range []string{"服务状态", "数据备份", "数据恢复", "/health", "/openapi.json"} {
if !strings.Contains(rrSystem.Body.String(), want) {
t.Fatalf("expected system HTML to contain %q", want)
}
@ -3774,7 +3774,7 @@ func TestUI_SystemManagementPagesUseSystemManagementCrumb(t *testing.T) {
path string
want string
}{
{path: "/ui/system", want: "系统管理 / 系统状态"},
{path: "/ui/system", want: "服务状态"},
{path: "/ui/audit", want: "系统管理 / 日志审计 / 审计记录"},
{path: "/ui/api", want: "系统管理 / 日志审计 / 高级调试"},
} {
@ -4480,7 +4480,7 @@ func TestUI_SystemPageShowsDatabaseBackupAction(t *testing.T) {
html := renderPage(t, ui, "/ui/system")
for _, want := range []string{
"数据备份 / 恢复",
"数据备份",
"恢复数据库",
`class="btn ghost js-export-db"`,
`data-export-url="/ui/system/db-backup"`,