Redesign admin UI with Chinese light theme

This commit is contained in:
2026-03-04 15:00:52 +08:00
parent f212b68c2c
commit 4348ee799b
8 changed files with 363 additions and 424 deletions

View File

@@ -14,14 +14,14 @@ let clearAnnouncementTimer
let unsubscribeAnnouncements = () => {}
const navItems = [
{ label: 'Dashboard', name: 'dashboard', icon: 'DataAnalysis' },
{ label: 'Bindings', name: 'bindings', icon: 'Connection' },
{ label: 'Logs', name: 'logs', icon: 'WarningFilled' },
{ label: 'Settings', name: 'settings', icon: 'Setting' },
{ label: '总览看板', name: 'dashboard', icon: 'DataAnalysis' },
{ label: '绑定管理', name: 'bindings', icon: 'Connection' },
{ label: '拦截日志', name: 'logs', icon: 'WarningFilled' },
{ label: '运行设置', name: 'settings', icon: 'Setting' },
]
const hideShell = computed(() => Boolean(route.meta.public))
const currentSection = computed(() => route.meta.kicker || 'Operations')
const currentSection = computed(() => route.meta.kicker || '控制台')
function updateClock() {
clockLabel.value = new Intl.DateTimeFormat(undefined, {
@@ -65,7 +65,7 @@ onBeforeUnmount(() => {
<router-view v-if="hideShell" />
<div v-else class="shell">
<a class="skip-link" href="#main-content">Skip to main content</a>
<a class="skip-link" href="#main-content">跳转到主要内容</a>
<div class="shell-glow shell-glow--mint" />
<div class="shell-glow shell-glow--amber" />
@@ -74,8 +74,8 @@ onBeforeUnmount(() => {
<div class="brand-mark">S</div>
<div>
<p class="eyebrow">Key-IP Sentinel</p>
<h1 class="brand-title">Control Plane</h1>
<p class="brand-subtitle">First-use bind enforcement edge</p>
<h1 class="brand-title">安全控制台</h1>
<p class="brand-subtitle">API Key 首次使用 IP 绑定网关</p>
</div>
</div>
@@ -93,23 +93,23 @@ onBeforeUnmount(() => {
</nav>
<div class="sidebar-note">
<p class="eyebrow">Operating mode</p>
<h3>Zero-trust token perimeter</h3>
<p class="eyebrow">当前能力</p>
<h3>绑定审计告警一体化</h3>
<p class="muted">
Every API key is pinned to the first observed client address or CIDR and inspected at the edge.
所有请求先经过边界网关首次调用自动绑定来源地址后续按 IP CIDR 持续校验
</p>
</div>
<div class="rail-grid">
<div class="rail-card">
<span class="rail-label">Surface</span>
<strong>Admin UI</strong>
<span class="rail-meta">JWT protected</span>
<span class="rail-label">入口</span>
<strong>管理后台</strong>
<span class="rail-meta">JWT 鉴权</span>
</div>
<div class="rail-card">
<span class="rail-label">Proxy</span>
<strong>Streaming</strong>
<span class="rail-meta">SSE passthrough</span>
<span class="rail-label">网关</span>
<strong>流式代理</strong>
<span class="rail-meta">支持 SSE 透传</span>
</div>
</div>
</aside>
@@ -119,20 +119,20 @@ onBeforeUnmount(() => {
<div class="header-copy">
<p class="eyebrow">{{ currentSection }}</p>
<h2 id="page-title" class="page-title">{{ route.meta.title || 'Sentinel' }}</h2>
<p class="muted header-note">Edge policy, runtime settings, and operator visibility in one secure surface.</p>
<p class="muted header-note">围绕绑定记录拦截日志和运行设置的统一运维入口</p>
</div>
<div class="header-actions">
<div class="header-chip-group">
<div class="header-chip">
<span class="header-chip-label">Mode</span>
<strong>Secure Proxy</strong>
<span class="header-chip-label">模式</span>
<strong>安全代理</strong>
</div>
<div class="header-chip" aria-live="polite">
<span class="header-chip-label">Updated</span>
<span class="header-chip-label">时间</span>
<strong>{{ clockLabel }}</strong>
</div>
</div>
<el-button type="primary" plain @click="logout">Logout</el-button>
<el-button type="primary" plain @click="logout">退出登录</el-button>
</div>
</header>
@@ -147,10 +147,10 @@ onBeforeUnmount(() => {
.shell {
position: relative;
display: grid;
grid-template-columns: 300px minmax(0, 1fr);
gap: 24px;
grid-template-columns: 276px minmax(0, 1fr);
gap: 18px;
min-height: 100vh;
padding: 24px;
padding: 18px;
}
.shell-sidebar,
@@ -162,8 +162,8 @@ onBeforeUnmount(() => {
.shell-sidebar {
display: flex;
flex-direction: column;
gap: 28px;
padding: 28px;
gap: 20px;
padding: 22px;
}
.brand-block {
@@ -175,19 +175,19 @@ onBeforeUnmount(() => {
.brand-mark {
display: grid;
place-items: center;
width: 56px;
height: 56px;
border-radius: 18px;
background: linear-gradient(135deg, rgba(17, 231, 181, 0.95), rgba(21, 132, 214, 0.95));
color: #071016;
font-size: 1.45rem;
width: 48px;
height: 48px;
border-radius: 16px;
background: linear-gradient(135deg, #6ea7ff, #86c8ff);
color: #ffffff;
font-size: 1.2rem;
font-weight: 800;
}
.brand-title,
.page-title {
margin: 0;
font-size: clamp(1.5rem, 2vw, 2.1rem);
font-size: clamp(1.2rem, 1.6vw, 1.6rem);
}
.nav-list {
@@ -199,19 +199,20 @@ onBeforeUnmount(() => {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-radius: 18px;
padding: 12px 14px;
border-radius: 16px;
color: var(--sentinel-ink-soft);
text-decoration: none;
transition: transform 160ms ease, background 160ms ease, color 160ms ease, box-shadow 160ms ease;
font-size: 0.95rem;
}
.nav-link:hover,
.nav-link.is-active {
color: var(--sentinel-ink);
background: rgba(7, 176, 147, 0.14);
box-shadow: inset 0 0 0 1px rgba(7, 176, 147, 0.18);
transform: translateX(4px);
background: rgba(114, 163, 255, 0.14);
box-shadow: inset 0 0 0 1px rgba(114, 163, 255, 0.2);
transform: translateX(3px);
}
.nav-icon {
@@ -220,15 +221,16 @@ onBeforeUnmount(() => {
.sidebar-note {
margin-top: auto;
padding: 18px;
padding: 16px;
border-radius: 22px;
background: linear-gradient(180deg, rgba(8, 31, 45, 0.92), rgba(10, 26, 35, 0.8));
color: #f3fffd;
background: linear-gradient(180deg, rgba(244, 248, 255, 0.98), rgba(235, 243, 255, 0.92));
color: var(--sentinel-ink);
border: 1px solid rgba(122, 164, 255, 0.18);
}
.sidebar-note h3 {
margin: 10px 0;
font-size: 1.15rem;
font-size: 1rem;
}
.shell-main {
@@ -236,7 +238,7 @@ onBeforeUnmount(() => {
z-index: 1;
display: flex;
flex-direction: column;
gap: 24px;
gap: 18px;
min-width: 0;
}
@@ -244,8 +246,8 @@ onBeforeUnmount(() => {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
padding: 22px 26px;
gap: 16px;
padding: 18px 20px;
}
.header-actions {
@@ -257,7 +259,7 @@ onBeforeUnmount(() => {
.shell-content {
display: flex;
flex-direction: column;
gap: 24px;
gap: 18px;
min-width: 0;
}
@@ -272,19 +274,19 @@ onBeforeUnmount(() => {
}
.shell-glow--mint {
top: 80px;
right: 160px;
width: 240px;
height: 240px;
background: rgba(17, 231, 181, 0.22);
top: 60px;
right: 120px;
width: 220px;
height: 220px;
background: rgba(132, 196, 255, 0.2);
}
.shell-glow--amber {
bottom: 100px;
left: 420px;
width: 280px;
height: 280px;
background: rgba(255, 170, 76, 0.18);
bottom: 80px;
left: 360px;
width: 260px;
height: 260px;
background: rgba(177, 221, 255, 0.18);
}
@media (max-width: 1080px) {