feat: Real-time Outbound Traffic, UI Improvements & Fix (#3629)

* Refactor HTML and JavaScript for improved UI and functionality

- Cleaned up JavaScript methods in subscription.js for better readability.
- Updated inbounds.html to clarify traffic update handling and removed unnecessary comments.
- Enhanced xray.html by correcting casing in routingDomainStrategies.
- Added mobile touch scrolling styles in page.html for better tab navigation on small screens.
- Streamlined vless.html by removing redundant line breaks and improving form layout.
- Refined subscription subpage.html for better structure and user experience.
- Adjusted outbounds.html to improve button visibility and functionality.
- Updated xray_traffic_job.go to ensure accurate traffic updates and real-time UI refresh.

* Refactor client traffic handling in InboundService

- Updated addClientTraffic method to initialize onlineClients as an empty slice instead of nil.
- Improved clarity and consistency in handling empty onlineUsers scenario.

* Add WebSocket support for outbounds traffic updates

- Implemented WebSocket connection in xray.html to handle real-time updates for outbounds traffic.
- Enhanced xray_traffic_job.go to retrieve and broadcast outbounds traffic updates.
- Introduced MessageTypeOutbounds in hub.go for managing outbounds messages.
- Added BroadcastOutbounds function in notifier.go to facilitate broadcasting outbounds updates to connected clients.

---------

Co-authored-by: lolka1333 <test123@gmail.com>
This commit is contained in:
lolka1333
2026-01-05 05:50:40 +01:00
committed by GitHub
parent a9770e1da2
commit 4800f8fb70
11 changed files with 260 additions and 239 deletions
+3 -20
View File
@@ -1608,24 +1608,9 @@
// Listen for traffic updates
window.wsClient.on('traffic', (payload) => {
if (payload && payload.clientTraffics && Array.isArray(payload.clientTraffics)) {
// Update client traffic statistics
payload.clientTraffics.forEach(clientTraffic => {
const dbInbound = this.dbInbounds.find(ib => {
if (!ib) return false;
const clients = this.getInboundClients(ib);
return clients && Array.isArray(clients) && clients.some(c => c && c.email === clientTraffic.email);
});
if (dbInbound && dbInbound.clientStats && Array.isArray(dbInbound.clientStats)) {
const stats = dbInbound.clientStats.find(s => s && s.email === clientTraffic.email);
if (stats) {
stats.up = clientTraffic.up || stats.up;
stats.down = clientTraffic.down || stats.down;
stats.total = clientTraffic.total || stats.total;
}
}
});
}
// Note: Do NOT update total consumed traffic (stats.up, stats.down) from this event
// because clientTraffics contains delta/incremental values, not total accumulated values.
// Total traffic is updated via the 'inbounds' event which contains accumulated values from database.
// Update online clients list in real-time
if (payload && Array.isArray(payload.onlineClients)) {
@@ -1645,8 +1630,6 @@
}
});
// Notifications disabled - white notifications are not needed
// Fallback to polling if WebSocket fails
window.wsClient.on('error', () => {
console.warn('WebSocket connection failed, falling back to polling');