- web/: React + Vite + TypeScript 前端 - backend/: Django + DRF + SimpleJWT 后端 - prototype/: HTML 设计原型 - docs/: PRD 和设计评审文档 - test: 单元测试 + E2E 极限测试
491 lines
21 KiB
HTML
491 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>仪表盘 — Jimeng Admin</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--bg-page: #0a0a0f;
|
||
--bg-sidebar: #111118;
|
||
--bg-card: #16161e;
|
||
--border: #2a2a38;
|
||
--primary: #00b8e6;
|
||
--primary-dim: rgba(0,184,230,0.12);
|
||
--text-1: #ffffff;
|
||
--text-2: #8a8a9a;
|
||
--text-3: #4a4a5a;
|
||
--hover: rgba(255,255,255,0.06);
|
||
--success: #34d399;
|
||
--danger: #f87171;
|
||
--warning: #fbbf24;
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: 'Noto Sans SC', 'Space Grotesk', system-ui, sans-serif;
|
||
background: var(--bg-page);
|
||
color: var(--text-1);
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
.layout { display: flex; height: 100vh; }
|
||
|
||
/* Sidebar */
|
||
.sidebar {
|
||
width: 240px;
|
||
min-width: 240px;
|
||
background: var(--bg-sidebar);
|
||
border-right: 1px solid var(--border);
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 0;
|
||
}
|
||
.sidebar-logo {
|
||
padding: 20px 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.sidebar-logo svg { flex-shrink: 0; }
|
||
.sidebar-logo span { font-size: 15px; font-weight: 600; letter-spacing: -0.3px; }
|
||
.sidebar-nav { flex: 1; padding: 12px 8px; display: flex; flex-direction: column; gap: 2px; }
|
||
.nav-item {
|
||
display: flex; align-items: center; gap: 12px;
|
||
padding: 10px 16px; border-radius: 8px;
|
||
font-size: 14px; color: var(--text-2);
|
||
text-decoration: none; transition: all 0.15s;
|
||
cursor: pointer;
|
||
}
|
||
.nav-item:hover { background: var(--hover); color: var(--text-1); }
|
||
.nav-item.active {
|
||
background: rgba(255,255,255,0.08);
|
||
color: var(--text-1); font-weight: 500;
|
||
}
|
||
.nav-item svg { opacity: 0.6; }
|
||
.nav-item.active svg, .nav-item:hover svg { opacity: 1; }
|
||
.sidebar-footer {
|
||
padding: 16px;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.sidebar-footer a {
|
||
display: flex; align-items: center; gap: 8px;
|
||
font-size: 13px; color: var(--text-3);
|
||
text-decoration: none; padding: 8px 12px;
|
||
border-radius: 6px; transition: all 0.15s;
|
||
}
|
||
.sidebar-footer a:hover { color: var(--text-2); background: var(--hover); }
|
||
|
||
/* Main content */
|
||
.main { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
|
||
.topbar {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 16px 32px; border-bottom: 1px solid var(--border);
|
||
flex-shrink: 0; background: var(--bg-page);
|
||
position: sticky; top: 0; z-index: 10;
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
.topbar-left h1 { font-size: 18px; font-weight: 600; }
|
||
.topbar-right { display: flex; align-items: center; gap: 12px; }
|
||
.admin-badge {
|
||
font-size: 12px; color: var(--primary);
|
||
padding: 4px 12px; background: var(--primary-dim);
|
||
border-radius: 6px; font-weight: 500;
|
||
}
|
||
.topbar-btn {
|
||
padding: 6px 14px; background: transparent;
|
||
border: 1px solid var(--border); border-radius: 6px;
|
||
color: var(--text-2); font-size: 13px; cursor: pointer;
|
||
transition: all 0.15s;
|
||
}
|
||
.topbar-btn:hover { background: var(--hover); color: var(--text-1); }
|
||
|
||
.content { padding: 28px 32px; flex: 1; }
|
||
|
||
/* Time range selector */
|
||
.time-range {
|
||
display: flex; gap: 4px; background: rgba(255,255,255,0.04);
|
||
border-radius: 8px; padding: 3px;
|
||
}
|
||
.time-range button {
|
||
padding: 6px 14px; border: none; border-radius: 6px;
|
||
background: transparent; color: var(--text-2); font-size: 12px;
|
||
cursor: pointer; transition: all 0.15s; font-weight: 500;
|
||
}
|
||
.time-range button.active {
|
||
background: var(--primary); color: #fff;
|
||
}
|
||
.time-range button:hover:not(.active) { color: var(--text-1); }
|
||
|
||
/* Stat cards */
|
||
.stat-card {
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 20px 24px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.stat-card::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0; right: 0;
|
||
width: 80px; height: 80px;
|
||
border-radius: 0 0 0 80px;
|
||
opacity: 0.04;
|
||
}
|
||
.stat-card:nth-child(1)::after { background: var(--primary); }
|
||
.stat-card:nth-child(2)::after { background: var(--success); }
|
||
.stat-card:nth-child(3)::after { background: var(--warning); }
|
||
.stat-card:nth-child(4)::after { background: #a78bfa; }
|
||
.stat-icon {
|
||
width: 36px; height: 36px; border-radius: 8px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
margin-bottom: 14px;
|
||
}
|
||
.stat-label { font-size: 13px; color: var(--text-2); margin-bottom: 6px; }
|
||
.stat-value {
|
||
font-family: 'JetBrains Mono', 'Space Grotesk', monospace;
|
||
font-size: 28px; font-weight: 700; letter-spacing: -1px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.stat-trend {
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
font-size: 12px; font-weight: 500;
|
||
padding: 2px 8px; border-radius: 4px;
|
||
}
|
||
.stat-trend.up { color: var(--success); background: rgba(52,211,153,0.1); }
|
||
.stat-trend.down { color: var(--danger); background: rgba(248,113,113,0.1); }
|
||
|
||
/* Chart cards */
|
||
.chart-card {
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 24px;
|
||
}
|
||
.chart-header {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
margin-bottom: 20px;
|
||
}
|
||
.chart-title { font-size: 15px; font-weight: 600; }
|
||
|
||
/* SVG Chart styles */
|
||
.chart-grid-line { stroke: rgba(255,255,255,0.04); stroke-width: 1; }
|
||
.chart-axis-label { fill: var(--text-3); font-size: 10px; font-family: 'JetBrains Mono', monospace; }
|
||
.chart-line { fill: none; stroke: var(--primary); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
||
.chart-area { fill: url(#areaGradient); }
|
||
.chart-dot { fill: var(--primary); }
|
||
.chart-tooltip-bg { fill: #1e1e2e; stroke: var(--border); rx: 6; }
|
||
.chart-tooltip-text { fill: var(--text-1); font-size: 11px; font-family: 'JetBrains Mono', monospace; }
|
||
|
||
/* Bar chart */
|
||
.bar-item {
|
||
display: flex; align-items: center; gap: 12px;
|
||
padding: 8px 0;
|
||
}
|
||
.bar-rank {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 12px; color: var(--text-3);
|
||
width: 20px; text-align: center;
|
||
}
|
||
.bar-rank.top { color: var(--primary); font-weight: 600; }
|
||
.bar-username {
|
||
width: 80px; font-size: 13px; color: var(--text-2);
|
||
text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
|
||
}
|
||
.bar-track {
|
||
flex: 1; height: 24px; background: rgba(255,255,255,0.03);
|
||
border-radius: 4px; overflow: hidden; position: relative;
|
||
}
|
||
.bar-fill {
|
||
height: 100%; border-radius: 4px;
|
||
background: linear-gradient(90deg, var(--primary), rgba(0,184,230,0.6));
|
||
transition: width 0.6s cubic-bezier(0.16, 1, 0.3, 1);
|
||
display: flex; align-items: center; justify-content: flex-end;
|
||
padding-right: 8px;
|
||
}
|
||
.bar-fill-value {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 11px; color: #fff; font-weight: 500;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Scrollbar */
|
||
::-webkit-scrollbar { width: 4px; }
|
||
::-webkit-scrollbar-track { background: transparent; }
|
||
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
|
||
|
||
/* Load animation */
|
||
@keyframes fadeUp {
|
||
from { opacity: 0; transform: translateY(12px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
.animate-in { animation: fadeUp 0.4s ease-out forwards; opacity: 0; }
|
||
.delay-1 { animation-delay: 0.05s; }
|
||
.delay-2 { animation-delay: 0.1s; }
|
||
.delay-3 { animation-delay: 0.15s; }
|
||
.delay-4 { animation-delay: 0.2s; }
|
||
.delay-5 { animation-delay: 0.3s; }
|
||
.delay-6 { animation-delay: 0.4s; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="layout">
|
||
<!-- Sidebar -->
|
||
<aside class="sidebar">
|
||
<div class="sidebar-logo">
|
||
<svg width="24" height="24" viewBox="0 0 28 28" fill="none">
|
||
<path d="M4 8L14 2L24 8V20L14 26L4 20V8Z" fill="#00b8e6" opacity="0.9"/>
|
||
<path d="M14 2L24 8L14 14L4 8L14 2Z" fill="#33ccf0"/>
|
||
</svg>
|
||
<span>Jimeng Admin</span>
|
||
</div>
|
||
<nav class="sidebar-nav">
|
||
<a href="admin-dashboard.html" class="nav-item active">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
|
||
仪表盘
|
||
</a>
|
||
<a href="admin-users.html" class="nav-item">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
|
||
用户管理
|
||
</a>
|
||
<a href="admin-records.html" class="nav-item">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
|
||
消费记录
|
||
</a>
|
||
<a href="admin-settings.html" class="nav-item">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
|
||
系统设置
|
||
</a>
|
||
</nav>
|
||
<div class="sidebar-footer">
|
||
<a href="video-generation.html">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
|
||
返回首页
|
||
</a>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Main -->
|
||
<div class="main">
|
||
<header class="topbar">
|
||
<div class="topbar-left">
|
||
<h1>仪表盘</h1>
|
||
</div>
|
||
<div class="topbar-right">
|
||
<div class="time-range">
|
||
<button>今日</button>
|
||
<button>近7天</button>
|
||
<button class="active">近30天</button>
|
||
<button>自定义</button>
|
||
</div>
|
||
<span class="admin-badge">Admin</span>
|
||
<button class="topbar-btn">退出</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="content">
|
||
<!-- Stats Grid -->
|
||
<div class="grid grid-cols-4 gap-4 mb-6 max-lg:grid-cols-2">
|
||
<div class="stat-card animate-in delay-1">
|
||
<div class="stat-icon" style="background: var(--primary-dim);">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#00b8e6" stroke-width="2"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
|
||
</div>
|
||
<div class="stat-label">总用户数</div>
|
||
<div class="stat-value">1,234</div>
|
||
<span class="stat-trend up">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/></svg>
|
||
+12.3%
|
||
</span>
|
||
</div>
|
||
|
||
<div class="stat-card animate-in delay-2">
|
||
<div class="stat-icon" style="background: rgba(52,211,153,0.12);">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="2"><path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="8.5" cy="7" r="4"/><line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/></svg>
|
||
</div>
|
||
<div class="stat-label">今日新增用户</div>
|
||
<div class="stat-value">+23</div>
|
||
<span class="stat-trend up">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/></svg>
|
||
+15.0%
|
||
</span>
|
||
</div>
|
||
|
||
<div class="stat-card animate-in delay-3">
|
||
<div class="stat-icon" style="background: rgba(251,191,36,0.12);">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||
</div>
|
||
<div class="stat-label">今日消费秒数</div>
|
||
<div class="stat-value">4,560<span style="font-size:14px;color:var(--text-2);font-weight:400">s</span></div>
|
||
<span class="stat-trend down">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="transform:rotate(180deg)"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/></svg>
|
||
-5.2%
|
||
</span>
|
||
</div>
|
||
|
||
<div class="stat-card animate-in delay-4">
|
||
<div class="stat-icon" style="background: rgba(167,139,250,0.12);">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
||
</div>
|
||
<div class="stat-label">本月消费秒数</div>
|
||
<div class="stat-value">89,010<span style="font-size:14px;color:var(--text-2);font-weight:400">s</span></div>
|
||
<span class="stat-trend up">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/></svg>
|
||
+8.7%
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Trend Chart -->
|
||
<div class="chart-card mb-6 animate-in delay-5">
|
||
<div class="chart-header">
|
||
<div class="chart-title">消费趋势(近30天)</div>
|
||
<div style="font-size:12px;color:var(--text-3)">单位:秒</div>
|
||
</div>
|
||
<svg viewBox="0 0 800 280" style="width:100%;height:auto" id="trendChart">
|
||
<defs>
|
||
<linearGradient id="areaGradient" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0%" stop-color="#00b8e6" stop-opacity="0.25"/>
|
||
<stop offset="100%" stop-color="#00b8e6" stop-opacity="0"/>
|
||
</linearGradient>
|
||
</defs>
|
||
<!-- Grid lines -->
|
||
<line x1="50" y1="20" x2="50" y2="240" class="chart-grid-line"/>
|
||
<line x1="50" y1="240" x2="780" y2="240" class="chart-grid-line"/>
|
||
<line x1="50" y1="185" x2="780" y2="185" class="chart-grid-line" stroke-dasharray="4,4"/>
|
||
<line x1="50" y1="130" x2="780" y2="130" class="chart-grid-line" stroke-dasharray="4,4"/>
|
||
<line x1="50" y1="75" x2="780" y2="75" class="chart-grid-line" stroke-dasharray="4,4"/>
|
||
<line x1="50" y1="20" x2="780" y2="20" class="chart-grid-line" stroke-dasharray="4,4"/>
|
||
|
||
<!-- Y axis labels -->
|
||
<text x="44" y="244" text-anchor="end" class="chart-axis-label">0</text>
|
||
<text x="44" y="189" text-anchor="end" class="chart-axis-label">50</text>
|
||
<text x="44" y="134" text-anchor="end" class="chart-axis-label">100</text>
|
||
<text x="44" y="79" text-anchor="end" class="chart-axis-label">150</text>
|
||
<text x="44" y="24" text-anchor="end" class="chart-axis-label">200</text>
|
||
|
||
<!-- X axis labels -->
|
||
<text x="74" y="260" class="chart-axis-label">3/1</text>
|
||
<text x="196" y="260" class="chart-axis-label">3/6</text>
|
||
<text x="318" y="260" class="chart-axis-label">3/11</text>
|
||
<text x="440" y="260" class="chart-axis-label">3/16</text>
|
||
<text x="562" y="260" class="chart-axis-label">3/21</text>
|
||
<text x="684" y="260" class="chart-axis-label">3/26</text>
|
||
<text x="756" y="260" class="chart-axis-label">3/30</text>
|
||
|
||
<!-- Area fill -->
|
||
<path class="chart-area" d="
|
||
M74,190 L98,175 L122,180 L146,160 L170,155 L194,145 L218,150
|
||
L242,140 L266,120 L290,130 L314,105 L338,95 L362,110
|
||
L386,85 L410,75 L434,90 L458,80 L482,95 L506,70
|
||
L530,60 L554,75 L578,55 L602,65 L626,50 L650,60
|
||
L674,45 L698,55 L722,40 L746,50 L756,48
|
||
L756,240 L74,240 Z"/>
|
||
|
||
<!-- Line -->
|
||
<path class="chart-line" d="
|
||
M74,190 L98,175 L122,180 L146,160 L170,155 L194,145 L218,150
|
||
L242,140 L266,120 L290,130 L314,105 L338,95 L362,110
|
||
L386,85 L410,75 L434,90 L458,80 L482,95 L506,70
|
||
L530,60 L554,75 L578,55 L602,65 L626,50 L650,60
|
||
L674,45 L698,55 L722,40 L746,50 L756,48"/>
|
||
|
||
<!-- Dots on key points -->
|
||
<circle cx="74" cy="190" r="3" class="chart-dot"/>
|
||
<circle cx="314" cy="105" r="3" class="chart-dot"/>
|
||
<circle cx="506" cy="70" r="3" class="chart-dot"/>
|
||
<circle cx="722" cy="40" r="3" class="chart-dot"/>
|
||
<circle cx="756" cy="48" r="3" class="chart-dot"/>
|
||
|
||
<!-- Hover tooltip example -->
|
||
<g style="opacity:0.9">
|
||
<rect x="690" y="8" width="80" height="36" class="chart-tooltip-bg" stroke-width="1" rx="6"/>
|
||
<text x="730" y="23" text-anchor="middle" class="chart-tooltip-text" font-weight="500">3/28</text>
|
||
<text x="730" y="37" text-anchor="middle" class="chart-tooltip-text" fill="#00b8e6">188s</text>
|
||
</g>
|
||
</svg>
|
||
</div>
|
||
|
||
<!-- Ranking Chart -->
|
||
<div class="chart-card animate-in delay-6">
|
||
<div class="chart-header">
|
||
<div class="chart-title">用户消费排行 Top 10</div>
|
||
<div style="font-size:12px;color:var(--text-3)">本月累计消费秒数</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;gap:4px">
|
||
<div class="bar-item">
|
||
<span class="bar-rank top">1</span>
|
||
<span class="bar-username">zhang_wei</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:100%"><span class="bar-fill-value">2,340s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank top">2</span>
|
||
<span class="bar-username">li_ming</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:81%"><span class="bar-fill-value">1,890s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank top">3</span>
|
||
<span class="bar-username">wang_fang</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:67%"><span class="bar-fill-value">1,560s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">4</span>
|
||
<span class="bar-username">chen_jie</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:58%"><span class="bar-fill-value">1,350s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">5</span>
|
||
<span class="bar-username">liu_yang</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:49%"><span class="bar-fill-value">1,140s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">6</span>
|
||
<span class="bar-username">zhao_lei</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:42%"><span class="bar-fill-value">980s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">7</span>
|
||
<span class="bar-username">huang_mei</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:35%"><span class="bar-fill-value">820s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">8</span>
|
||
<span class="bar-username">sun_qiang</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:28%"><span class="bar-fill-value">650s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">9</span>
|
||
<span class="bar-username">wu_xia</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:21%"><span class="bar-fill-value">490s</span></div></div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<span class="bar-rank">10</span>
|
||
<span class="bar-username">zhou_min</span>
|
||
<div class="bar-track"><div class="bar-fill" style="width:15%"><span class="bar-fill-value">350s</span></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div style="text-align:center;padding:24px 0 8px;font-size:11px;color:var(--text-3)">
|
||
Jimeng Clone Admin v3.0
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// Time range button interaction
|
||
document.querySelectorAll('.time-range button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelector('.time-range .active')?.classList.remove('active');
|
||
btn.classList.add('active');
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|