Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'web/html/inbounds.html')
-rw-r--r--web/html/inbounds.html121
1 files changed, 108 insertions, 13 deletions
diff --git a/web/html/inbounds.html b/web/html/inbounds.html
index 86bde2c8..4e1149ae 100644
--- a/web/html/inbounds.html
+++ b/web/html/inbounds.html
@@ -1128,8 +1128,11 @@
},
openEditClient(dbInboundId, client) {
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
clients = this.getInboundClients(dbInbound);
+ if (!clients || !Array.isArray(clients)) return;
index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ if (index < 0) return;
clientModal.show({
title: '{{ i18n "pages.client.edit"}}',
okText: '{{ i18n "pages.client.submitEdit"}}',
@@ -1144,11 +1147,14 @@
});
},
findIndexOfClient(protocol, clients, client) {
+ if (!clients || !Array.isArray(clients) || !client) {
+ return -1;
+ }
switch (protocol) {
case Protocols.TROJAN:
case Protocols.SHADOWSOCKS:
- return clients.findIndex(item => item.password === client.password && item.email === client.email);
- default: return clients.findIndex(item => item.id === client.id && item.email === client.email);
+ return clients.findIndex(item => item && item.password === client.password && item.email === client.email);
+ default: return clients.findIndex(item => item && item.id === client.id && item.email === client.email);
}
},
async addClient(clients, dbInboundId, modal) {
@@ -1271,11 +1277,15 @@
},
showInfo(dbInboundId, client) {
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
index = 0;
if (dbInbound.isMultiUser()) {
inbound = dbInbound.toInbound();
- clients = inbound.clients;
- index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ clients = inbound && inbound.clients ? inbound.clients : null;
+ if (clients && Array.isArray(clients)) {
+ index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ if (index < 0) index = 0;
+ }
}
newDbInbound = this.checkFallback(dbInbound);
infoModal.show(newDbInbound, index);
@@ -1288,9 +1298,12 @@
async switchEnableClient(dbInboundId, client) {
this.loading()
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
inbound = dbInbound.toInbound();
- clients = inbound.clients;
+ clients = inbound && inbound.clients ? inbound.clients : null;
+ if (!clients || !Array.isArray(clients)) return;
index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ if (index < 0 || !clients[index]) return;
clients[index].enable = !clients[index].enable;
clientId = this.getClientId(dbInbound.protocol, clients[index]);
await this.updateClient(clients[index], dbInboundId, clientId);
@@ -1303,7 +1316,9 @@
}
},
getInboundClients(dbInbound) {
- return dbInbound.toInbound().clients;
+ if (!dbInbound) return null;
+ const inbound = dbInbound.toInbound();
+ return inbound && inbound.clients ? inbound.clients : null;
},
resetClientTraffic(client, dbInboundId, confirmation = true) {
if (confirmation) {
@@ -1443,7 +1458,12 @@
formatLastOnline(email) {
const ts = this.getLastOnline(email)
if (!ts) return '-'
- return IntlUtil.formatDate(ts)
+ // Check if IntlUtil is available (may not be loaded yet)
+ if (typeof IntlUtil !== 'undefined' && IntlUtil.formatDate) {
+ return IntlUtil.formatDate(ts)
+ }
+ // Fallback to simple date formatting if IntlUtil is not available
+ return new Date(ts).toLocaleString()
},
isRemovable(dbInboundId) {
return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1;
@@ -1567,13 +1587,88 @@
}
this.loading();
this.getDefaultSettings();
- if (this.isRefreshEnabled) {
- this.startDataRefreshLoop();
- }
- else {
- this.getDBInbounds();
+
+ // Initial data fetch
+ this.getDBInbounds().then(() => {
+ this.loading(false);
+ });
+
+ // Setup WebSocket for real-time updates
+ if (window.wsClient) {
+ window.wsClient.connect();
+
+ // Listen for inbounds updates
+ window.wsClient.on('inbounds', (payload) => {
+ if (payload && Array.isArray(payload)) {
+ // Use setInbounds to properly convert to DBInbound objects with methods
+ this.setInbounds(payload);
+ this.searchInbounds(this.searchKey);
+ }
+ });
+
+ // 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;
+ }
+ }
+ });
+ }
+
+ // Update online clients list in real-time
+ if (payload && Array.isArray(payload.onlineClients)) {
+ this.onlineClients = payload.onlineClients;
+ // Recalculate client counts to update online status
+ this.dbInbounds.forEach(dbInbound => {
+ const inbound = this.inbounds.find(ib => ib.id === dbInbound.id);
+ if (inbound && this.clientCount[dbInbound.id]) {
+ this.clientCount[dbInbound.id] = this.getClientCounts(dbInbound, inbound);
+ }
+ });
+ }
+
+ // Update last online map in real-time
+ if (payload && payload.lastOnlineMap && typeof payload.lastOnlineMap === 'object') {
+ this.lastOnlineMap = { ...this.lastOnlineMap, ...payload.lastOnlineMap };
+ }
+ });
+
+ // 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');
+ if (this.isRefreshEnabled) {
+ this.startDataRefreshLoop();
+ }
+ });
+
+ window.wsClient.on('disconnected', () => {
+ if (window.wsClient.reconnectAttempts >= window.wsClient.maxReconnectAttempts) {
+ console.warn('WebSocket reconnection failed, falling back to polling');
+ if (this.isRefreshEnabled) {
+ this.startDataRefreshLoop();
+ }
+ }
+ });
+ } else {
+ // Fallback to polling if WebSocket is not available
+ if (this.isRefreshEnabled) {
+ this.startDataRefreshLoop();
+ }
}
- this.loading(false);
},
computed: {
total() {