diff --git a/web/controller/inbound.go b/web/controller/inbound.go index e0f50410..a8003484 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -35,9 +35,11 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { g.POST("/addClient", a.addInboundClient) g.POST("/addGroupClient", a.addGroupInboundClient) g.POST("/:id/delClient/:clientId", a.delInboundClient) + g.POST("/delGroupClients", a.delGroupClients) g.POST("/updateClient/:clientId", a.updateInboundClient) g.POST("/updateClients", a.updateGroupInboundClient) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) + g.POST("/resetGroupClientTraffic", a.resetGroupClientTraffic) g.POST("/resetAllTraffics", a.resetAllTraffics) g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics) g.POST("/delDepletedClients/:id", a.delDepletedClients) @@ -241,6 +243,38 @@ func (a *InboundController) delInboundClient(c *gin.Context) { } } +func (a *InboundController) delGroupClients(c *gin.Context) { + var requestData []struct { + InboundID int `json:"inboundId"` + ClientID string `json:"clientId"` + } + + if err := c.ShouldBindJSON(&requestData); err != nil { + jsonMsg(c, "Invalid request data", err) + return + } + + needRestart := false + + for _, req := range requestData { + needRestartTmp, err := a.inboundService.DelInboundClient(req.InboundID, req.ClientID) + if err != nil { + jsonMsg(c, "Failed to delete client", err) + return + } + + if needRestartTmp { + needRestart = true + } + } + + jsonMsg(c, "Clients deleted successfully", nil) + + if needRestart { + a.xrayService.SetToNeedRestart() + } +} + func (a *InboundController) updateInboundClient(c *gin.Context) { clientId := c.Param("clientId") @@ -333,6 +367,44 @@ func (a *InboundController) resetClientTraffic(c *gin.Context) { } } +func (a *InboundController) resetGroupClientTraffic(c *gin.Context) { + var requestData []struct { + InboundID int `json:"inboundId"` // Map JSON "inboundId" to struct field "InboundID" + Email string `json:"email"` // Map JSON "email" to struct field "Email" + } + + // Parse JSON body directly using ShouldBindJSON + if err := c.ShouldBindJSON(&requestData); err != nil { + jsonMsg(c, "Invalid request data", err) + return + } + + needRestart := false + + // Process each request data + for _, req := range requestData { + needRestartTmp, err := a.inboundService.ResetClientTraffic(req.InboundID, req.Email) + if err != nil { + jsonMsg(c, "Failed to reset client traffic", err) + return + } + + // If any request requires a restart, set needRestart to true + if needRestartTmp { + needRestart = true + } + } + + // Send response back to the client + jsonMsg(c, "Traffic reset for all clients", nil) + + // Restart the service if required + if needRestart { + a.xrayService.SetToNeedRestart() + } +} + + func (a *InboundController) resetAllTraffics(c *gin.Context) { err := a.inboundService.ResetAllTraffics() if err != nil { diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index 3113b461..de7915a5 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -271,21 +271,20 @@ }, async resetClientTrafficHandler(client, dbInboundId, clients = []) { if (clients.length > 0) { - let response; - clients.forEach((client) => { - const inbound = clientModal.dbInbounds.find(inbound => inbound.id === client.inboundId) - if(inbound && app.hasClientStats(inbound, client.email)) { - response = HttpUtil.postWithModal('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email); - } - }) - return response; + const resetRequests = clients + .filter(client => { + const inbound = clientModal.dbInbounds.find(inbound => inbound.id === client.inboundId); + return inbound && app.hasClientStats(inbound, client.email); + }).map(client => ({ inboundId: client.inboundId, email: client.email})); + + return HttpUtil.postWithModalJson('/panel/inbound/resetGroupClientTraffic', resetRequests, null) } else { return HttpUtil.postWithModal('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email) } }, resetClientTraffic(client, dbInboundId, iconElement) { const subGroup = app.subSettings.enable && clientModal.group.isGroup && clientModal.group.canGroup && clientModal.dbInbounds && clientModal.dbInbounds.length > 0 ? app.getSubGroupClients(clientModal.dbInbounds, client) : []; - const clients = subGroup && subGroup.clients && subGroup.clients.length > 0 ? subGroup.clients : []; + const clients = subGroup && subGroup.clients && subGroup.clients.length > 1 ? subGroup.clients : []; this.$confirm({ title: '{{ i18n "pages.inbounds.resetTraffic"}}', content: '{{ i18n "pages.inbounds.resetTrafficContent"}}', diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index dce0da0b..854b0808 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -1145,6 +1145,8 @@ }, async delClientHandler(dbInboundId, currentClient, clients = []) { if (clients.length > 0) { + const deleteRequestData = []; + for (const client of clients) { const dbInbound = this.dbInbounds.find(inbound => inbound.id === client.inboundId); if (dbInbound) { @@ -1161,9 +1163,14 @@ await this.submit(`/panel/inbound/addClient`, data, null); } } + + deleteRequestData.push({ + inboundId: client.inboundId, + clientId: client.clientId, + }); } - await this.submit(`/panel/inbound/${client.inboundId}/delClient/${client.clientId}`); } + await this.submit('/panel/inbound/delGroupClients', deleteRequestData, null, true); } else { const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); const clientId = this.getClientId(dbInbound.protocol, currentClient); @@ -1172,7 +1179,7 @@ }, delClient(dbInboundId, currentClient, confirmation = true) { const subGroup = this.subSettings.enable ? this.getSubGroupClients(this.dbInbounds, currentClient) : []; - const clients = subGroup && subGroup.clients && subGroup.clients.length > 0 ? subGroup.clients : []; + const clients = subGroup && subGroup.clients && subGroup.clients.length > 1 ? subGroup.clients : []; if (confirmation){ const clientEmails = clients.length > 0 ? clients.map(item => item.email) : currentClient.email this.$confirm({ @@ -1295,19 +1302,20 @@ }, resetClientTrafficHandler(client, dbInboundId, clients = []) { if (clients.length > 0){ - clients.forEach(async (client) => { - const inbound = this.dbInbounds.find(inbound => inbound.id === client.inboundId) - if(inbound && this.hasClientStats(inbound, client.email)) { - await this.submit('/panel/inbound/' + client.inboundId + '/resetClientTraffic/' + client.email) - } - }) + const resetRequests = clients + .filter(client => { + const inbound = this.dbInbounds.find(inbound => inbound.id === client.inboundId); + return inbound && this.hasClientStats(inbound, client.email); + }).map(client => ({ inboundId: client.inboundId, email: client.email})); + + this.submit('/panel/inbound/resetGroupClientTraffic', resetRequests, null, true) }else { this.submit('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email); } }, resetClientTraffic(client, dbInboundId, confirmation = true) { const subGroup = this.subSettings.enable ? this.getSubGroupClients(this.dbInbounds, client) : []; - const clients = subGroup && subGroup.clients && subGroup.clients.length > 0 ? subGroup.clients : []; + const clients = subGroup && subGroup.clients && subGroup.clients.length > 1 ? subGroup.clients : []; if (confirmation){ const clientEmails = clients.length > 0 ? clients.map(item => item.email) : client.email this.$confirm({