feat: add shared PostgreSQL fnOS service and refresh UI

This commit is contained in:
2026-08-02 20:14:39 +08:00
parent de9f5ae110
commit e5b50ea85c
52 changed files with 3577 additions and 338 deletions
+18 -25
View File
@@ -1,6 +1,6 @@
/* =============================================================
Live Recorder · Design System
商业级 SaaS · 浅色侧栏 + 层次投影 + 移动适配
紧凑 NAS 管理台 · 信息优先 + 低动画 + 移动适配
Base: Element Plus 2.x overrides
============================================================= */
@@ -71,8 +71,8 @@
--sidebar-w-collapsed: 72px;
--topbar-h: 62px;
--page-max: 1320px;
--page-gap: 22px;
--content-padding: 28px;
--page-gap: 16px;
--content-padding: 20px;
--content-padding-mobile: 14px;
--control-height: 40px;
--control-height-sm: 34px;
@@ -191,9 +191,9 @@ button { font-family: inherit; cursor: pointer; }
/* ============================ Page layout ============================ */
.page-stack { display: grid; gap: var(--page-gap); width: min(100%, var(--page-max)); margin: 0 auto; }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; animation: fadeUp .3s ease both; }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.page-header > div:first-child { flex: 1; min-width: 0; }
.page-title { margin: 0; font-size: 28px; font-weight: 800; letter-spacing: -.025em; line-height: 1.2; color: var(--text-primary); }
.page-title { margin: 0; font-size: 24px; font-weight: 750; letter-spacing: -.02em; line-height: 1.25; color: var(--text-primary); }
.page-subtitle { max-width: 76ch; margin: 8px 0 0; color: var(--text-muted); font-size: 13.5px; line-height: 1.6; }
.page-kicker { margin-bottom: 7px; color: var(--accent); font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.page-toolbar, .header-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex-shrink: 0; }
@@ -202,28 +202,22 @@ button { font-family: inherit; cursor: pointer; }
.surface-card {
--el-card-bg-color: transparent;
border-radius: var(--radius-md); border: 1px solid var(--border-subtle);
background: var(--surface); box-shadow: var(--shadow-sm); transition: box-shadow .18s ease; animation: fadeUp .3s ease both;
background: var(--surface); box-shadow: var(--shadow-xs);
}
.surface-card:hover { box-shadow: var(--shadow-md); }
.surface-card .el-card__body { padding: 24px; }
.surface-card:hover { box-shadow: var(--shadow-sm); }
.surface-card .el-card__body { padding: 18px; }
/* stat grid / KPI cards */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.stat-card {
display: grid; gap: 11px; min-height: auto; padding: 20px; border-radius: var(--radius-md);
border: 1px solid var(--border-subtle); background: var(--surface); box-shadow: var(--shadow-sm);
transition: box-shadow .18s, transform .18s; position: relative; overflow: hidden;
animation: fadeUp .35s ease both;
display: grid; gap: 6px; min-height: auto; padding: 12px 14px; border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle); background: var(--surface); box-shadow: none;
position: relative; overflow: hidden;
}
.stat-card:nth-child(2) { animation-delay: .05s; }
.stat-card:nth-child(3) { animation-delay: .10s; }
.stat-card:nth-child(4) { animation-delay: .15s; }
.stat-card:nth-child(5) { animation-delay: .20s; }
.stat-card:nth-child(6) { animation-delay: .25s; }
.stat-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.stat-card:hover { border-color: var(--border-base); }
.stat-card__label { color: var(--text-muted); font-size: 12.5px; font-weight: 600; }
.stat-card__value { color: var(--text-primary); font-size: 31px; font-weight: 800; letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-card__hint { color: var(--text-muted); font-size: 12.5px; line-height: 1.65; font-weight: 500; }
.stat-card__value { color: var(--text-primary); font-size: 24px; font-weight: 750; letter-spacing: -.03em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat-card__hint { color: var(--text-muted); font-size: 11.5px; line-height: 1.45; font-weight: 500; }
/* section */
.section-title { margin: 0 0 6px; color: var(--text-primary); font-size: 16px; font-weight: 700; letter-spacing: -.01em; }
@@ -280,7 +274,7 @@ button { font-family: inherit; cursor: pointer; }
/* buttons */
.el-button { min-height: var(--control-height); padding: 0 15px; border-radius: var(--radius-sm); font-weight: 700; letter-spacing: 0; transition: all .15s ease; }
.el-button:not(.is-disabled):hover { transform: translateY(-1px); }
.el-button:not(.is-disabled):hover { transform: none; }
.el-button.el-button--default:not(.is-text):not(.is-link) { border-color: var(--border-base); background: var(--surface); color: var(--text-secondary); box-shadow: none; }
.el-button.el-button--default:not(.is-text):not(.is-link):hover { border-color: var(--text-soft); color: var(--text-primary); box-shadow: var(--shadow-xs); }
@@ -370,8 +364,7 @@ html[data-theme="dark"] .el-table tbody tr:nth-child(even) { background: rgba(25
.skel--title { height: 18px; width: 50%; }
/* ============================ Motion ============================ */
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition-duration: 0.01ms !important; } }
/* ============================ Responsive ============================ */
@media (max-width: 1280px) { .stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .highlight-grid { grid-template-columns: 1fr; } }
@@ -379,7 +372,7 @@ html[data-theme="dark"] .el-table tbody tr:nth-child(even) { background: rgba(25
@media (max-width: 768px) {
.page-header, .section-header, .toolbar-row { flex-direction: column; }
.page-title { font-size: 22px; }
.page-subtitle { margin-top: 6px; font-size: 12.5px; line-height: 1.6; }
.page-subtitle { display: none; }
.surface-card .el-card__body { padding: 14px; }
.stats-grid, .data-card__grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
.stat-card { padding: 14px; gap: 8px; }