video-shuoshan/prototype/admin-settings.html
zyc ffe92f7b15 Initial commit: 即梦视频生成平台
- web/: React + Vite + TypeScript 前端
- backend/: Django + DRF + SimpleJWT 后端
- prototype/: HTML 设计原型
- docs/: PRD 和设计评审文档
- test: 单元测试 + E2E 极限测试
2026-03-13 09:59:33 +08:00

204 lines
11 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;
}
* { 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 { width: 240px; min-width: 240px; background: var(--bg-sidebar); border-right: 1px solid var(--border); display: flex; flex-direction: column; }
.sidebar-logo { padding: 20px 24px; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--border); }
.sidebar-logo span { font-size: 15px; font-weight: 600; }
.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 { 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 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; max-width: 680px; }
.settings-card {
background: var(--bg-card); border: 1px solid var(--border);
border-radius: 12px; padding: 28px; margin-bottom: 24px;
}
.settings-card-header {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 24px;
}
.settings-card-title { font-size: 16px; font-weight: 600; }
.settings-card-desc { font-size: 13px; color: var(--text-2); margin-top: 4px; }
.form-field { margin-bottom: 20px; }
.form-label { display: block; font-size: 13px; color: var(--text-2); margin-bottom: 8px; font-weight: 500; }
.form-input {
width: 100%; height: 44px; padding: 0 14px;
background: rgba(255,255,255,0.04); border: 1px solid var(--border);
border-radius: 8px; color: var(--text-1); font-size: 14px;
font-family: 'JetBrains Mono', monospace; outline: none; transition: border-color 0.2s;
}
.form-input:focus { border-color: var(--primary); }
.form-hint { font-size: 12px; color: var(--text-3); margin-top: 6px; }
.form-textarea {
width: 100%; min-height: 120px; padding: 12px 14px;
background: rgba(255,255,255,0.04); border: 1px solid var(--border);
border-radius: 8px; color: var(--text-1); font-size: 14px;
font-family: 'Noto Sans SC', system-ui, sans-serif;
outline: none; resize: vertical; transition: border-color 0.2s;
line-height: 1.6;
}
.form-textarea:focus { border-color: var(--primary); }
.save-btn {
padding: 10px 28px; background: var(--primary); border: none;
border-radius: 8px; color: #fff; font-size: 14px; font-weight: 500;
cursor: pointer; transition: opacity 0.15s;
}
.save-btn:hover { opacity: 0.9; }
/* Toggle switch */
.toggle-wrap { display: flex; align-items: center; gap: 10px; }
.toggle {
width: 44px; height: 24px; border-radius: 12px;
background: var(--border); position: relative;
cursor: pointer; transition: background 0.2s;
}
.toggle.on { background: var(--primary); }
.toggle::after {
content: '';
position: absolute; top: 2px; left: 2px;
width: 20px; height: 20px; border-radius: 50%;
background: #fff; transition: transform 0.2s;
}
.toggle.on::after { transform: translateX(20px); }
.toggle-label { font-size: 13px; color: var(--text-2); }
/* Toast */
.toast {
position: fixed; top: 24px; right: 24px;
background: var(--bg-card); border: 1px solid var(--success);
border-radius: 8px; padding: 12px 20px;
display: flex; align-items: center; gap: 8px;
font-size: 13px; color: var(--success);
transform: translateX(120%); transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
z-index: 1000;
}
.toast.show { transform: translateX(0); }
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
@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.1s; }
</style>
</head>
<body>
<div class="layout">
<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"><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 active"><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>
<div class="main">
<header class="topbar">
<h1>系统设置</h1>
<div class="topbar-right">
<span class="admin-badge">Admin</span>
<button class="topbar-btn">退出</button>
</div>
</header>
<div class="content">
<!-- Quota settings -->
<div class="settings-card animate-in">
<div class="settings-card-header">
<div>
<div class="settings-card-title">全局默认配额</div>
<div class="settings-card-desc">新注册用户将自动获得此配额设置</div>
</div>
</div>
<div class="form-field">
<label class="form-label">默认每日限额 (秒)</label>
<input type="number" class="form-input" value="600">
<div class="form-hint">每位用户每天最多可消费的视频生成秒数</div>
</div>
<div class="form-field">
<label class="form-label">默认每月限额 (秒)</label>
<input type="number" class="form-input" value="6000">
<div class="form-hint">每位用户每月最多可消费的视频生成秒数</div>
</div>
<button class="save-btn" onclick="showToast()">保存配额设置</button>
</div>
<!-- Announcement settings -->
<div class="settings-card animate-in delay-1">
<div class="settings-card-header">
<div>
<div class="settings-card-title">系统公告</div>
<div class="settings-card-desc">启用后公告内容将展示在用户端页面顶部</div>
</div>
<div class="toggle-wrap">
<span class="toggle-label">启用公告</span>
<div class="toggle on" id="toggleAnnounce" onclick="this.classList.toggle('on')"></div>
</div>
</div>
<div class="form-field">
<label class="form-label">公告内容</label>
<textarea class="form-textarea" placeholder="输入公告内容...">系统将于 2026年3月15日 02:00-06:00 进行维护升级,届时服务将暂停使用,请提前做好安排。</textarea>
</div>
<button class="save-btn" onclick="showToast()">保存公告</button>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
设置已保存
</div>
<script>
function showToast() {
const toast = document.getElementById('toast');
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 2000);
}
</script>
</body>
</html>