4-tab layout (Dashboard/Proxies/Profiles/Tools) with dark theme. New pages: rules.html (Custom Rules + Rule Sets tabs), profiles.html, proxies.html, tools.html, logs.html. Removed: home, dashboard, nodes, status, dns, firewall. Design system: #0F172A bg, #4F52B4 accent, Inter font, card-based, no emoji icons.
149 lines
6.5 KiB
HTML
149 lines
6.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<title>Sing - Dashboard</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
<div class="app-shell">
|
|
<div class="page-content" id="page">
|
|
|
|
<!-- Page Header -->
|
|
<div class="page-header">
|
|
<h1>Dashboard</h1>
|
|
<div class="header-right">
|
|
<div class="status-dot online" id="statusDot"></div>
|
|
<span class="status-label online" id="statusLabel">Online</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Outbound Mode -->
|
|
<div class="section-header mt-8">
|
|
<svg class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v18M3 12l9-9 9 9"/></svg>
|
|
<span>Outbound Mode</span>
|
|
</div>
|
|
<div class="card">
|
|
<div class="chip-row" id="modeChips">
|
|
<div class="chip active" data-mode="0">Rule-based</div>
|
|
<div class="chip" data-mode="1">Global proxy</div>
|
|
<div class="chip" data-mode="2">Direct</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Connect / Disconnect -->
|
|
<div class="toggle-card connected mt-12" id="toggleCard" onclick="toggleVPN()">
|
|
<div class="toggle-icon" id="toggleIcon">■</div>
|
|
<div class="toggle-info">
|
|
<div class="toggle-title" id="toggleTitle">Disconnect</div>
|
|
<div class="toggle-subtitle" id="toggleSubtitle">Tokyo-VLESS-Reality</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Traffic -->
|
|
<div class="section-header mt-16">
|
|
<svg class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
|
|
<span>Traffic</span>
|
|
</div>
|
|
<div class="card">
|
|
<div class="traffic-grid">
|
|
<div class="traffic-col">
|
|
<div class="arrow up">↑</div>
|
|
<div class="speed" id="upSpeed">12.4 KB/s</div>
|
|
<div class="total" id="upTotal">1.24 GB</div>
|
|
</div>
|
|
<div class="traffic-col">
|
|
<div class="arrow down">↓</div>
|
|
<div class="speed" id="downSpeed">156.8 KB/s</div>
|
|
<div class="total" id="downTotal">8.92 GB</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Connection / Node info grid -->
|
|
<div class="info-grid mt-12">
|
|
<div class="card">
|
|
<div class="section-header">
|
|
<svg class="icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
|
|
<span>Node</span>
|
|
</div>
|
|
<div style="font-size:15px;font-weight:500;margin-top:4px;" id="nodeNameInfo">Tokyo-VLESS-Reality</div>
|
|
<div style="font-size:12px;color:var(--text-secondary);margin-top:2px;" id="nodeProtoInfo">VLESS + Reality</div>
|
|
<div style="font-family:var(--font-mono);font-size:13px;color:var(--accent);margin-top:4px;" id="uptimeInfo">01:23:45</div>
|
|
</div>
|
|
<div class="card" style="cursor:pointer;" onclick="location.href='connections.html'">
|
|
<div class="section-header">
|
|
<svg class="icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><circle cx="6" cy="6" r="1"/><circle cx="6" cy="18" r="1"/></svg>
|
|
<span>Connections</span>
|
|
</div>
|
|
<div style="font-family:var(--font-mono);font-size:28px;font-weight:600;color:var(--accent);margin-top:4px;" id="connCount">42</div>
|
|
<div style="font-size:12px;color:var(--accent);margin-top:2px;">View all ›</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Bottom Tab Bar -->
|
|
<nav class="tab-bar">
|
|
<a href="index.html" class="active">
|
|
<span class="tab-icon"><svg viewBox="0 0 24 24"><path d="M4 13h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1zm0 8h6a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1zm10 0h6a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1zm0-18v4a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1z"/></svg></span>
|
|
Dashboard
|
|
</a>
|
|
<a href="proxies.html">
|
|
<span class="tab-icon"><svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg></span>
|
|
Proxies
|
|
</a>
|
|
<a href="profiles.html">
|
|
<span class="tab-icon"><svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg></span>
|
|
Profiles
|
|
</a>
|
|
<a href="tools.html">
|
|
<span class="tab-icon"><svg viewBox="0 0 24 24"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"/></svg></span>
|
|
Tools
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
|
|
<script>
|
|
// VPN toggle
|
|
let connected = true;
|
|
function toggleVPN() {
|
|
connected = !connected;
|
|
const card = document.getElementById('toggleCard');
|
|
const icon = document.getElementById('toggleIcon');
|
|
const title = document.getElementById('toggleTitle');
|
|
const subtitle = document.getElementById('toggleSubtitle');
|
|
const dot = document.getElementById('statusDot');
|
|
const label = document.getElementById('statusLabel');
|
|
|
|
if (connected) {
|
|
card.classList.add('connected');
|
|
icon.innerHTML = '\u25A0'; // stop square
|
|
title.textContent = 'Disconnect';
|
|
subtitle.textContent = 'Tokyo-VLESS-Reality';
|
|
dot.className = 'status-dot online';
|
|
label.className = 'status-label online';
|
|
label.textContent = 'Online';
|
|
} else {
|
|
card.classList.remove('connected');
|
|
icon.innerHTML = '\u25B6'; // play triangle
|
|
title.textContent = 'Connect';
|
|
subtitle.textContent = 'Not connected';
|
|
dot.className = 'status-dot offline';
|
|
label.className = 'status-label offline';
|
|
label.textContent = 'Offline';
|
|
}
|
|
}
|
|
|
|
// Outbound mode chips
|
|
document.getElementById('modeChips').addEventListener('click', function(e) {
|
|
const chip = e.target.closest('.chip');
|
|
if (!chip) return;
|
|
this.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));
|
|
chip.classList.add('active');
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|