275 lines
11 KiB
HTML
275 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">
|
||
<title>管理控制台 · 路由拓扑</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body class="admin-page">
|
||
|
||
<div class="console" id="console">
|
||
<!-- ================= 左侧深蓝可收缩侧栏 ================= -->
|
||
<aside class="console-nav">
|
||
<div class="console-brand">
|
||
<div class="logo">R</div>
|
||
<div class="cb-text"><b>管理控制台</b><i id="navUser">—</i></div>
|
||
<button class="cnav-toggle" id="btnCollapseNav" title="收起 / 展开侧栏">☰</button>
|
||
</div>
|
||
|
||
<div class="cnav-item active" data-view="overview"><span class="ci">📊</span><span class="cl">概览</span></div>
|
||
<div class="cnav-item" data-view="users"><span class="ci">👥</span><span class="cl">用户管理</span></div>
|
||
<div class="cnav-item" data-view="topo"><span class="ci">🗺️</span><span class="cl">拓扑管理</span></div>
|
||
<div class="cnav-item" data-view="settings"><span class="ci">⚙️</span><span class="cl">网站设置</span></div>
|
||
<div class="cnav-item" data-view="logs"><span class="ci">📝</span><span class="cl">操作日志</span></div>
|
||
|
||
<div class="cnav-foot">
|
||
<div class="cnav-close" id="btnCloseAdmin"><span class="ci">←</span><span class="cl">返回拓扑</span></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- ================= 右侧主区域 ================= -->
|
||
<main class="console-main">
|
||
|
||
<!-- 概览 -->
|
||
<section class="view" id="view-overview">
|
||
<div class="view-head"><h2>概览</h2></div>
|
||
<div class="cards" id="statCards"></div>
|
||
<div class="split">
|
||
<div class="panel">
|
||
<div class="panel-title">最近操作</div>
|
||
<div class="mini-list" id="recentLogs"></div>
|
||
</div>
|
||
<div class="panel">
|
||
<div class="panel-title">最近拓扑</div>
|
||
<div class="mini-list" id="recentTopos"></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 用户管理 -->
|
||
<section class="view" id="view-users" hidden>
|
||
<div class="view-head"><h2>用户管理</h2></div>
|
||
<div class="tabs" id="userTabs">
|
||
<div class="tab active" data-tab="list">用户列表</div>
|
||
<div class="tab" data-tab="groups">分组管理</div>
|
||
</div>
|
||
|
||
<div class="tab-pane" id="userTab-list">
|
||
<div class="tools-inline">
|
||
<input class="search" id="userSearch" placeholder="搜索用户名 / 角色" spellcheck="false">
|
||
<button class="btn primary" id="btnNewUser">+ 新建用户</button>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table class="grid">
|
||
<thead><tr>
|
||
<th>用户名</th><th>角色</th><th>状态</th><th>登录次数</th><th>最近登录</th><th>创建时间</th><th>操作</th>
|
||
</tr></thead>
|
||
<tbody id="userRows"></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="pager" id="userPager"></div>
|
||
</div>
|
||
|
||
<div class="tab-pane" id="userTab-groups" hidden>
|
||
<div class="tools-inline">
|
||
<button class="btn primary" id="btnNewGroup">+ 新建分组</button>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table class="grid">
|
||
<thead><tr>
|
||
<th>分组名称</th><th>描述</th><th>成员数</th><th>创建时间</th><th>操作</th>
|
||
</tr></thead>
|
||
<tbody id="groupRows"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 拓扑管理 -->
|
||
<section class="view" id="view-topo" hidden>
|
||
<div class="view-head">
|
||
<h2>拓扑管理</h2>
|
||
<div class="view-tools">
|
||
<input class="search" id="topoSearch" placeholder="搜索拓扑名称" spellcheck="false">
|
||
<select class="search" id="topoOwner"></select>
|
||
<button class="btn" id="btnExportSelectedTopos">导出所选</button>
|
||
<button class="btn" id="btnExportAllTopos">导出全部</button>
|
||
<button class="btn danger" id="btnDeleteSelectedTopos">删除所选</button>
|
||
</div>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table class="grid">
|
||
<thead><tr>
|
||
<th class="col-chk"><input type="checkbox" id="topoSelectAll" title="全选本页"></th>
|
||
<th>名称</th><th>所有者</th><th>可见性</th><th>节点 / 连线</th><th>更新时间</th><th>操作</th>
|
||
</tr></thead>
|
||
<tbody id="topoRows"></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="pager" id="topoPager"></div>
|
||
</section>
|
||
|
||
<!-- 网站设置 -->
|
||
<section class="view" id="view-settings" hidden>
|
||
<div class="view-head">
|
||
<h2>网站设置</h2>
|
||
<div class="view-tools">
|
||
<button class="btn primary" id="btnSaveSettings">保存设置</button>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<div class="panel">
|
||
<div class="panel-title">品牌</div>
|
||
<label class="set-label">网站名称
|
||
<input class="search" id="setSiteName" type="text" placeholder="路由拓扑" spellcheck="false" maxlength="40">
|
||
</label>
|
||
<div class="set-label">网站 Logo</div>
|
||
<div class="logo-edit">
|
||
<div class="logo-preview" id="logoPreview">R</div>
|
||
<div class="logo-edit-side">
|
||
<input type="file" id="logoFile" accept="image/png,image/jpeg,image/gif,image/webp,image/svg+xml" hidden>
|
||
<div class="row-mini">
|
||
<button class="btn" id="btnPickLogo" type="button">选择图片</button>
|
||
<button class="btn" id="btnClearLogo" type="button">清除</button>
|
||
</div>
|
||
<div class="hint-sm">支持 PNG / JPG / GIF / WEBP / SVG,建议方形透明底,不超过 300KB。</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel">
|
||
<div class="panel-title">注册与会话</div>
|
||
<label class="set-row">
|
||
<input type="checkbox" id="setAllowReg"> <span>开放访客自助注册</span>
|
||
</label>
|
||
<label class="set-label">会话有效期(天)
|
||
<input class="search" id="setTtl" type="number" min="1" max="365" step="1">
|
||
</label>
|
||
<div class="hint-sm">修改后,新登录的会话按该时长计算有效期(1 - 365 天)。</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 操作日志 -->
|
||
<section class="view" id="view-logs" hidden>
|
||
<div class="view-head">
|
||
<h2>操作日志</h2>
|
||
<div class="view-tools"><input class="search" id="logSearch" placeholder="搜索用户 / 动作 / 详情" spellcheck="false"></div>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table class="grid">
|
||
<thead><tr>
|
||
<th>时间</th><th>用户</th><th>动作</th><th>对象</th><th>详情</th><th>IP</th>
|
||
</tr></thead>
|
||
<tbody id="logRows"></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="pager" id="logPager"></div>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
|
||
<!-- ================= 新建用户 ================= -->
|
||
<div class="overlay" id="userOverlay" hidden>
|
||
<div class="dialog">
|
||
<div class="dlg-head"><h2 id="userDlgTitle">新建用户</h2><span class="dlg-close" id="btnCloseUser">×</span></div>
|
||
<label>用户名
|
||
<input id="uName" type="text" spellcheck="false" autocomplete="off" placeholder="2-32 位字母、数字、_ . -">
|
||
</label>
|
||
<label>密码
|
||
<input id="uPass" type="password" autocomplete="new-password" placeholder="至少 8 位,需含字母和数字">
|
||
</label>
|
||
<label>角色
|
||
<select id="uRole">
|
||
<option value="user">普通用户</option>
|
||
<option value="admin">管理员</option>
|
||
</select>
|
||
</label>
|
||
<div class="dlg-tip">新建用户首次登录后需强制修改密码</div>
|
||
<div class="dlg-err" id="userErr"></div>
|
||
<div class="dlg-actions">
|
||
<button class="btn" id="btnCancelUser" type="button">取消</button>
|
||
<button class="btn primary" id="btnSaveUser" type="button">创建</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 重置用户密码 ================= -->
|
||
<div class="overlay" id="resetOverlay" hidden>
|
||
<div class="dialog">
|
||
<div class="dlg-head"><h2>重置用户密码</h2><span class="dlg-close" id="btnCloseReset">×</span></div>
|
||
<div class="dlg-tip" id="resetTip"></div>
|
||
<label>您的密码(管理员)
|
||
<input id="resetAdminPw" type="password" autocomplete="current-password" placeholder="请输入当前登录账号的密码">
|
||
</label>
|
||
<label>新密码
|
||
<input id="resetNewPw" type="password" autocomplete="new-password" placeholder="至少 8 位,需含字母和数字">
|
||
</label>
|
||
<label>确认新密码
|
||
<input id="resetNewPw2" type="password" autocomplete="new-password" placeholder="请再次输入新密码">
|
||
</label>
|
||
<label class="pwd-show"><input type="checkbox" id="resetShow"> 显示密码</label>
|
||
<div class="dlg-err" id="resetErr"></div>
|
||
<div class="dlg-actions">
|
||
<button class="btn" id="btnCancelReset" type="button">取消</button>
|
||
<button class="btn primary" id="btnDoReset" type="button">确认重置</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 新建 / 编辑 分组 ================= -->
|
||
<div class="overlay" id="groupOverlay" hidden>
|
||
<div class="dialog">
|
||
<div class="dlg-head"><h2 id="groupDlgTitle">新建分组</h2><span class="dlg-close" id="btnCloseGroup">×</span></div>
|
||
<label>分组名称
|
||
<input id="gName" type="text" spellcheck="false" maxlength="40" placeholder="例如:红队 / 运维组">
|
||
</label>
|
||
<label>描述
|
||
<input id="gDesc" type="text" spellcheck="false" maxlength="120" placeholder="可选">
|
||
</label>
|
||
<div class="dlg-err" id="groupErr"></div>
|
||
<div class="dlg-actions">
|
||
<button class="btn" id="btnCancelGroup" type="button">取消</button>
|
||
<button class="btn primary" id="btnSaveGroup" type="button">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 管理分组成员 ================= -->
|
||
<div class="overlay" id="memberOverlay" hidden>
|
||
<div class="dialog wide share-dialog">
|
||
<div class="dlg-head"><h2 id="memberDlgTitle">管理成员</h2><span class="dlg-close" id="btnCloseMember">×</span></div>
|
||
<div class="dlg-msg" id="memberMsg"></div>
|
||
<input class="search" id="memberFilter" placeholder="搜索用户" spellcheck="false">
|
||
<div class="share-list" id="memberList"></div>
|
||
<div class="dlg-err" id="memberErr"></div>
|
||
<div class="dlg-actions">
|
||
<button class="btn" id="btnCancelMember" type="button">取消</button>
|
||
<button class="btn primary" id="btnSaveMember" type="button">保存成员</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 站内确认 / 输入弹窗 ================= -->
|
||
<div class="overlay" id="confirmOverlay" hidden>
|
||
<div class="dialog">
|
||
<div class="dlg-head"><h2 id="confirmTitle">请确认</h2><span class="dlg-close" id="confirmClose">×</span></div>
|
||
<div class="dlg-msg" id="confirmMsg"></div>
|
||
<label id="confirmFieldWrap" hidden><span id="confirmFieldLabel"></span>
|
||
<input id="confirmField" type="text" spellcheck="false" autocomplete="off">
|
||
</label>
|
||
<div class="dlg-err" id="confirmErr"></div>
|
||
<div class="dlg-actions">
|
||
<button class="btn" id="confirmCancel" type="button">取消</button>
|
||
<button class="btn primary" id="confirmOk" type="button">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script src="admin.js"></script>
|
||
</body>
|
||
</html>
|