mirror of
				https://github.com/MHSanaei/3x-ui.git
				synced 2025-10-27 02:24:40 +00:00 
			
		
		
		
	
							parent
							
								
									daa4354047
								
							
						
					
					
						commit
						9fba92d879
					
				
					 16 changed files with 57 additions and 388 deletions
				
			
		
							
								
								
									
										2
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/docker.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -36,6 +36,6 @@ jobs: | ||||||
|         with: |         with: | ||||||
|           context: . |           context: . | ||||||
|           push: ${{ github.event_name != 'pull_request' }} |           push: ${{ github.event_name != 'pull_request' }} | ||||||
|           platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386, linux/arm/v5 |           platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386 | ||||||
|           tags: ${{ steps.meta.outputs.tags }} |           tags: ${{ steps.meta.outputs.tags }} | ||||||
|           labels: ${{ steps.meta.outputs.labels }} |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|  |  | ||||||
|  | @ -25,10 +25,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install. | ||||||
| 
 | 
 | ||||||
| ## Install Custom Version | ## Install Custom Version | ||||||
| 
 | 
 | ||||||
| To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.1`: | To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.2`: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.1 | bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.2 | ||||||
| ``` | ``` | ||||||
| ## Manual Install & Upgrade | ## Manual Install & Upgrade | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| 2.1.1 | 2.1.2 | ||||||
|  | @ -83,41 +83,6 @@ class HttpUtil { | ||||||
|         } |         } | ||||||
|         return msg; |         return msg; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     static async jsonPost(url, data) { |  | ||||||
|         let msg; |  | ||||||
|         try { |  | ||||||
|             const requestOptions = { |  | ||||||
|                 method: 'POST', |  | ||||||
|                 headers: { |  | ||||||
|                     'Content-Type': 'application/json', |  | ||||||
|                 }, |  | ||||||
|                 body: JSON.stringify(data), |  | ||||||
|             }; |  | ||||||
|             const resp = await fetch(url, requestOptions); |  | ||||||
|             const response = await resp.json(); |  | ||||||
| 
 |  | ||||||
|             msg = this._respToMsg({data : response}); |  | ||||||
|         } catch (e) { |  | ||||||
|             msg = new Msg(false, e.toString()); |  | ||||||
|         } |  | ||||||
|         this._handleMsg(msg); |  | ||||||
|         return msg; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     static async postWithModalJson(url, data, modal) { |  | ||||||
|         if (modal) { |  | ||||||
|             modal.loading(true); |  | ||||||
|         } |  | ||||||
|         const msg = await this.jsonPost(url, data); |  | ||||||
|         if (modal) { |  | ||||||
|             modal.loading(false); |  | ||||||
|             if (msg instanceof Msg && msg.success) { |  | ||||||
|                 modal.close(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return msg; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class PromiseUtil { | class PromiseUtil { | ||||||
|  |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| package controller | package controller | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|     "errors" |  | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  | @ -33,9 +32,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g.POST("/clientIps/:email", a.getClientIps) | 	g.POST("/clientIps/:email", a.getClientIps) | ||||||
| 	g.POST("/clearClientIps/:email", a.clearClientIps) | 	g.POST("/clearClientIps/:email", a.clearClientIps) | ||||||
| 	g.POST("/addClient", a.addInboundClient) | 	g.POST("/addClient", a.addInboundClient) | ||||||
| 	g.POST("/addGroupClient", a.addGroupInboundClient) |  | ||||||
| 	g.POST("/:id/delClient/:clientId", a.delInboundClient) | 	g.POST("/:id/delClient/:clientId", a.delInboundClient) | ||||||
| 	g.POST("/updateClients", a.updateGroupInboundClient) |  | ||||||
| 	g.POST("/updateClient/:clientId", a.updateInboundClient) | 	g.POST("/updateClient/:clientId", a.updateInboundClient) | ||||||
| 	g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) | 	g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) | ||||||
| 	g.POST("/resetAllTraffics", a.resetAllTraffics) | 	g.POST("/resetAllTraffics", a.resetAllTraffics) | ||||||
|  | @ -163,51 +160,23 @@ func (a *InboundController) clearClientIps(c *gin.Context) { | ||||||
| 
 | 
 | ||||||
| func (a *InboundController) addInboundClient(c *gin.Context) { | func (a *InboundController) addInboundClient(c *gin.Context) { | ||||||
| 	data := &model.Inbound{} | 	data := &model.Inbound{} | ||||||
|     err := c.ShouldBind(data) | 	err := c.ShouldBind(data) | ||||||
|     if err != nil { | 	if err != nil { | ||||||
|         jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) | 		jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) | ||||||
|         return | 		return | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|     needRestart := true | 	needRestart := true | ||||||
| 
 |  | ||||||
|     needRestart, err = a.inboundService.AddInboundClient(data) |  | ||||||
|     if err != nil { |  | ||||||
|         jsonMsg(c, "Something went wrong!", err) |  | ||||||
|         return |  | ||||||
|     } |  | ||||||
|     jsonMsg(c, "Client(s) added", nil) |  | ||||||
|     if err == nil && needRestart { |  | ||||||
|         a.xrayService.SetToNeedRestart() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (a *InboundController) addGroupInboundClient(c *gin.Context) { |  | ||||||
| 	var requestData []model.Inbound |  | ||||||
| 
 |  | ||||||
|     err := c.ShouldBindJSON(&requestData) |  | ||||||
| 
 |  | ||||||
|     if err != nil { |  | ||||||
|         jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) |  | ||||||
|         return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     needRestart := true |  | ||||||
| 
 |  | ||||||
|     for _, data := range requestData { |  | ||||||
| 
 |  | ||||||
|         needRestart, err = a.inboundService.AddInboundClient(&data) |  | ||||||
|         if err != nil { |  | ||||||
|             jsonMsg(c, "Something went wrong!", err) |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     jsonMsg(c, "Client(s) added", nil) |  | ||||||
|     if err == nil && needRestart { |  | ||||||
|         a.xrayService.SetToNeedRestart() |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|  | 	needRestart, err = a.inboundService.AddInboundClient(data) | ||||||
|  | 	if err != nil { | ||||||
|  | 		jsonMsg(c, "Something went wrong!", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	jsonMsg(c, "Client(s) added", nil) | ||||||
|  | 	if err == nil && needRestart { | ||||||
|  | 		a.xrayService.SetToNeedRestart() | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *InboundController) delInboundClient(c *gin.Context) { | func (a *InboundController) delInboundClient(c *gin.Context) { | ||||||
|  | @ -254,56 +223,6 @@ func (a *InboundController) updateInboundClient(c *gin.Context) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *InboundController) updateGroupInboundClient(c *gin.Context) { |  | ||||||
|     var requestData []map[string]interface{} |  | ||||||
| 
 |  | ||||||
|     if err := c.ShouldBindJSON(&requestData); err != nil { |  | ||||||
|         jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) |  | ||||||
|         return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     needRestart := false |  | ||||||
| 
 |  | ||||||
|     for _, item := range requestData { |  | ||||||
| 
 |  | ||||||
|         inboundMap, ok := item["inbound"].(map[string]interface{}) |  | ||||||
|         if !ok { |  | ||||||
|             jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'inbound' to map")) |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         clientId, ok := item["clientId"].(string) |  | ||||||
|         if !ok { |  | ||||||
|             jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'clientId' to string")) |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         inboundJSON, err := json.Marshal(inboundMap) |  | ||||||
|         if err != nil { |  | ||||||
|             jsonMsg(c, "Something went wrong!", err) |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         var inboundModel model.Inbound |  | ||||||
|         if err := json.Unmarshal(inboundJSON, &inboundModel); err != nil { |  | ||||||
|             jsonMsg(c, "Something went wrong!", err) |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if restart, err := a.inboundService.UpdateInboundClient(&inboundModel, clientId); err != nil { |  | ||||||
|             jsonMsg(c, "Something went wrong!", err) |  | ||||||
|             return |  | ||||||
|         } else { |  | ||||||
|             needRestart = needRestart || restart |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     jsonMsg(c, "Client updated", nil) |  | ||||||
|     if needRestart { |  | ||||||
|         a.xrayService.SetToNeedRestart() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (a *InboundController) resetClientTraffic(c *gin.Context) { | func (a *InboundController) resetClientTraffic(c *gin.Context) { | ||||||
| 	id, err := strconv.Atoi(c.Param("id")) | 	id, err := strconv.Atoi(c.Param("id")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -11,12 +11,10 @@ | ||||||
|         <a-divider>Subscription</a-divider> |         <a-divider>Subscription</a-divider> | ||||||
|         <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas></div> |         <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas></div> | ||||||
|     </template> |     </template> | ||||||
|     <a-divider v-if="!isJustSub">{{ i18n "pages.inbounds.client" }}</a-divider> |     <a-divider>{{ i18n "pages.inbounds.client" }}</a-divider> | ||||||
|     <template v-if="!isJustSub"> |     <template v-for="(row, index) in qrModal.qrcodes"> | ||||||
|         <template v-for="(row, index) in qrModal.qrcodes"> |         <a-tag color="green" style="margin: 10px 0; display: block; text-align: center;">[[ row.remark ]]</a-tag> | ||||||
|             <a-tag color="green" style="margin: 10px 0; display: block; text-align: center;">[[ row.remark ]]</a-tag> |         <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas></div> | ||||||
|             <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas></div> |  | ||||||
|         </template> |  | ||||||
|     </template> |     </template> | ||||||
| </a-modal> | </a-modal> | ||||||
| 
 | 
 | ||||||
|  | @ -29,14 +27,12 @@ | ||||||
|         qrcodes: [], |         qrcodes: [], | ||||||
|         clipboard: null, |         clipboard: null, | ||||||
|         visible: false, |         visible: false, | ||||||
|         isJustSub: false, |  | ||||||
|         subId: '', |         subId: '', | ||||||
|         show: function (title = '', dbInbound, client, isJustSub = false) { |         show: function (title = '', dbInbound, client) { | ||||||
|             this.title = title; |             this.title = title; | ||||||
|             this.dbInbound = dbInbound; |             this.dbInbound = dbInbound; | ||||||
|             this.inbound = dbInbound.toInbound(); |             this.inbound = dbInbound.toInbound(); | ||||||
|             this.client = client; |             this.client = client; | ||||||
|             this.isJustSub = isJustSub; |  | ||||||
|             this.subId = ''; |             this.subId = ''; | ||||||
|             this.qrcodes = []; |             this.qrcodes = []; | ||||||
|             this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, client).forEach(l => { |             this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, client).forEach(l => { | ||||||
|  | @ -57,9 +53,6 @@ | ||||||
|         el: '#qrcode-modal', |         el: '#qrcode-modal', | ||||||
|         data: { |         data: { | ||||||
|             qrModal: qrModal, |             qrModal: qrModal, | ||||||
|             get isJustSub(){ |  | ||||||
|                return qrModal.isJustSub |  | ||||||
|             } |  | ||||||
|         }, |         }, | ||||||
|         methods: { |         methods: { | ||||||
|             copyToClipboard(elmentId, content) { |             copyToClipboard(elmentId, content) { | ||||||
|  |  | ||||||
|  | @ -15,16 +15,8 @@ | ||||||
|         confirmLoading: false, |         confirmLoading: false, | ||||||
|         title: '', |         title: '', | ||||||
|         okText: '', |         okText: '', | ||||||
|         group: { |         isEdit: false, | ||||||
|             canGroup: true, |  | ||||||
|             isGroup: false, |  | ||||||
|             currentClient: null, |  | ||||||
|             inbounds: [], |  | ||||||
|             clients: [], |  | ||||||
|             editIds: [] |  | ||||||
|         }, |  | ||||||
|         dbInbound: new DBInbound(), |         dbInbound: new DBInbound(), | ||||||
|         dbInbounds: null, |  | ||||||
|         inbound: new Inbound(), |         inbound: new Inbound(), | ||||||
|         clients: [], |         clients: [], | ||||||
|         clientStats: [], |         clientStats: [], | ||||||
|  | @ -33,136 +25,32 @@ | ||||||
|         clientIps: null, |         clientIps: null, | ||||||
|         delayedStart: false, |         delayedStart: false, | ||||||
|         ok() { |         ok() { | ||||||
|             if (clientModal.group.isGroup && clientModal.group.canGroup) { |             if (clientModal.isEdit) { | ||||||
|                 const currentClient = clientModal.group.currentClient; |                 ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.oldClientId); | ||||||
| 
 |  | ||||||
|                 clientModal.group.clients.forEach((client, index) => { |  | ||||||
|                     const { email, limitIp, totalGB, expiryTime, reset, enable, subId, tgId, flow } = currentClient; |  | ||||||
| 
 |  | ||||||
|                     const match = email.match(/^(.*?)__/); |  | ||||||
|                     const new_email = match ? match[1] : email; |  | ||||||
| 
 |  | ||||||
|                     client.email = `${new_email}__${index + 1}`; |  | ||||||
|                     client.limitIp = limitIp; |  | ||||||
|                     client.totalGB = totalGB; |  | ||||||
|                     client.expiryTime = expiryTime; |  | ||||||
|                     client.reset = reset; |  | ||||||
|                     client.enable = enable; |  | ||||||
| 
 |  | ||||||
|                     if (subId) { |  | ||||||
|                         client.subId = subId; |  | ||||||
|                     } |  | ||||||
|                     if (tgId) { |  | ||||||
|                         client.tgId = tgId; |  | ||||||
|                     } |  | ||||||
|                     if (flow) { |  | ||||||
|                         client.flow = flow; |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
| 
 |  | ||||||
|                 if (clientModal.isEdit) { |  | ||||||
|                     ObjectUtil.execute(clientModal.confirm, clientModal.group.clients, clientModal.group.inbounds, clientModal.group.editIds); |  | ||||||
|                 }else{ |  | ||||||
|                     ObjectUtil.execute(clientModal.confirm, clientModal.group.clients, clientModal.group.inbounds); |  | ||||||
|                 } |  | ||||||
|             } else { |             } else { | ||||||
|                 if (clientModal.isEdit){ |                 ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id); | ||||||
|                     ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id, clientModal.oldClientId); |  | ||||||
|                 }else{ |  | ||||||
|                     ObjectUtil.execute(clientModal.confirm, clientModalApp.client, clientModal.dbInbound.id); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         show({ title = '', okText = '{{ i18n "sure" }}', index = null, dbInbound = null, dbInbounds = null, confirm = () => { }, isEdit = false }) { |         show({ title = '', okText = '{{ i18n "sure" }}', index = null, dbInbound = null, confirm = () => { }, isEdit = false }) { | ||||||
|             this.group = { |  | ||||||
|                 canGroup: true, |  | ||||||
|                 isGroup: false, |  | ||||||
|                 currentClient: null, |  | ||||||
|                 inbounds: [], |  | ||||||
|                 clients: [], |  | ||||||
|                 editIds: [] |  | ||||||
|             } |  | ||||||
|             this.dbInbounds = dbInbounds; |  | ||||||
|             this.visible = true; |             this.visible = true; | ||||||
|             this.title = title; |             this.title = title; | ||||||
|             this.okText = okText; |             this.okText = okText; | ||||||
|             this.isEdit = isEdit; |             this.isEdit = isEdit; | ||||||
|             if (dbInbounds !== null && Array.isArray(dbInbounds)) { |  | ||||||
|                 if (isEdit) { |  | ||||||
|                     this.showProcess(dbInbound, index); |  | ||||||
|                     let processSingleEdit = true |  | ||||||
|                     if (this.group.canGroup){ |  | ||||||
|                         this.group.currentClient = this.clients[this.index] |  | ||||||
|                         const response = this.getGroupInboundsClients(dbInbounds,this.group.currentClient) |  | ||||||
|                         if (response.clients.length > 1){ |  | ||||||
|                             this.group.isGroup = true; |  | ||||||
|                             this.group.inbounds = response.inbounds |  | ||||||
|                             this.group.clients = response.clients |  | ||||||
|                             this.group.editIds = response.editIds |  | ||||||
|                             if (this.clients[index].expiryTime < 0) { |  | ||||||
|                                 this.delayedStart = true; |  | ||||||
|                             } |  | ||||||
|                             processSingleEdit = false |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     if(processSingleEdit){ |  | ||||||
|                         this.singleEditClientProcess(index) |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     this.group.isGroup = true; |  | ||||||
|                     dbInbounds.forEach((dbInboundItem) => { |  | ||||||
|                         this.showProcess(dbInboundItem); |  | ||||||
|                         this.addClient(this.inbound.protocol, this.clients); |  | ||||||
|                         this.group.inbounds.push(dbInboundItem.id) |  | ||||||
|                         this.group.clients.push(this.clients[this.index]) |  | ||||||
|                     }) |  | ||||||
|                     this.group.currentClient = this.clients[this.index] |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 this.showProcess(dbInbound, index); |  | ||||||
|                 if (isEdit) { |  | ||||||
|                     this.singleEditClientProcess(index) |  | ||||||
|                 } else { |  | ||||||
|                     this.addClient(this.inbound.protocol, this.clients); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email); |  | ||||||
|             this.confirm = confirm; |  | ||||||
|         }, |  | ||||||
|         showProcess(dbInbound, index = null) { |  | ||||||
|             this.dbInbound = new DBInbound(dbInbound); |             this.dbInbound = new DBInbound(dbInbound); | ||||||
|             this.inbound = dbInbound.toInbound(); |             this.inbound = dbInbound.toInbound(); | ||||||
|             this.clients = this.inbound.clients; |             this.clients = this.inbound.clients; | ||||||
|             this.index = index === null ? this.clients.length : index; |             this.index = index === null ? this.clients.length : index; | ||||||
|             this.delayedStart = false; |             this.delayedStart = false; | ||||||
|         }, |             if (isEdit) { | ||||||
|         singleEditClientProcess(index) { |                 if (this.clients[index].expiryTime < 0) { | ||||||
|             if (this.clients[index].expiryTime < 0) { |                     this.delayedStart = true; | ||||||
|                 this.delayedStart = true; |  | ||||||
|             } |  | ||||||
|             this.oldClientId = this.getClientId(this.dbInbound.protocol, this.clients[index]); |  | ||||||
|         }, |  | ||||||
|         getGroupInboundsClients(dbInbounds, currentClient) { |  | ||||||
|             const response = { |  | ||||||
|                 inbounds: [], |  | ||||||
|                 clients: [], |  | ||||||
|                 editIds: [] |  | ||||||
|             } |  | ||||||
|             dbInbounds.forEach((dbInboundItem) => { |  | ||||||
|                 const dbInbound = new DBInbound(dbInboundItem); |  | ||||||
|                 const inbound = dbInbound.toInbound(); |  | ||||||
|                 const clients = inbound.clients; |  | ||||||
|                 if (clients.length > 0){ |  | ||||||
|                     clients.forEach((client) => { |  | ||||||
|                         if (client['subId'] === currentClient['subId']){ |  | ||||||
|                             response.inbounds.push(dbInboundItem.id) |  | ||||||
|                             response.clients.push(client) |  | ||||||
|                             response.editIds.push(this.getClientId(dbInbound.protocol, client)) |  | ||||||
|                         } |  | ||||||
|                     }) |  | ||||||
|                 } |                 } | ||||||
|             }) |                 this.oldClientId = this.getClientId(dbInbound.protocol, clients[index]); | ||||||
|             return response; |             } else { | ||||||
|  |                 this.addClient(this.inbound.protocol, this.clients); | ||||||
|  |             } | ||||||
|  |             this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email); | ||||||
|  |             this.confirm = confirm; | ||||||
|         },   |         },   | ||||||
|         getClientId(protocol, client) { |         getClientId(protocol, client) { | ||||||
|             switch (protocol) { |             switch (protocol) { | ||||||
|  | @ -206,18 +94,6 @@ | ||||||
|             get isEdit() { |             get isEdit() { | ||||||
|                 return this.clientModal.isEdit; |                 return this.clientModal.isEdit; | ||||||
|             }, |             }, | ||||||
|             get isGroup() { |  | ||||||
|                 return this.clientModal.group.isGroup; |  | ||||||
|             }, |  | ||||||
|             get isGroupEdit() { |  | ||||||
|                 return this.clientModal.group.canGroup; |  | ||||||
|             }, |  | ||||||
|             set isGroupEdit(value) { |  | ||||||
|                 this.clientModal.group.canGroup = value; |  | ||||||
|                 if (!value){ |  | ||||||
|                     this.clientModal.singleEditClientProcess(this.clientModal.index) |  | ||||||
|                 } |  | ||||||
|             }, |  | ||||||
|             get datepicker() { |             get datepicker() { | ||||||
|                 return app.datepicker; |                 return app.datepicker; | ||||||
|             }, |             }, | ||||||
|  |  | ||||||
|  | @ -3,18 +3,6 @@ | ||||||
|     <a-form-item label='{{ i18n "pages.inbounds.enable" }}'> |     <a-form-item label='{{ i18n "pages.inbounds.enable" }}'> | ||||||
|         <a-switch v-model="client.enable"></a-switch> |         <a-switch v-model="client.enable"></a-switch> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item v-if="isEdit && app.subSettings.enable && isGroup"> |  | ||||||
|         <template slot="label"> |  | ||||||
|             <a-tooltip> |  | ||||||
|                 <template slot="title"> |  | ||||||
|                     <span>{{ i18n "pages.inbounds.isGroupEditDesc" }}</span> |  | ||||||
|                 </template> |  | ||||||
|                 {{ i18n "pages.inbounds.isGroupEdit" }} |  | ||||||
|                 <a-icon type="question-circle"></a-icon> |  | ||||||
|             </a-tooltip> |  | ||||||
|         </template> |  | ||||||
|         <a-switch v-model="isGroupEdit"></a-switch> |  | ||||||
|     </a-form-item> |  | ||||||
|     <a-form-item> |     <a-form-item> | ||||||
|         <template slot="label"> |         <template slot="label"> | ||||||
|             <a-tooltip> |             <a-tooltip> | ||||||
|  | @ -27,7 +15,7 @@ | ||||||
|         </template> |         </template> | ||||||
|         <a-input v-model.trim="client.email"></a-input> |         <a-input v-model.trim="client.email"></a-input> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item v-if="(inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS) && !isGroup"> |     <a-form-item v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS"> | ||||||
|         <template slot="label"> |         <template slot="label"> | ||||||
|             <a-tooltip> |             <a-tooltip> | ||||||
|                 <template slot="title"> |                 <template slot="title"> | ||||||
|  | @ -40,7 +28,7 @@ | ||||||
|         </template> |         </template> | ||||||
|         <a-input v-model.trim="client.password"></a-input> |         <a-input v-model.trim="client.password"></a-input> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item v-if="(inbound.protocol === Protocols.VMESS || inbound.protocol === Protocols.VLESS) && !isGroup"> |     <a-form-item v-if="inbound.protocol === Protocols.VMESS || inbound.protocol === Protocols.VLESS"> | ||||||
|         <template slot="label"> |         <template slot="label"> | ||||||
|             <a-tooltip> |             <a-tooltip> | ||||||
|                 <template slot="title"> |                 <template slot="title"> | ||||||
|  |  | ||||||
|  | @ -13,7 +13,6 @@ | ||||||
|         confirmLoading: false, |         confirmLoading: false, | ||||||
|         okText: '{{ i18n "sure" }}', |         okText: '{{ i18n "sure" }}', | ||||||
|         isEdit: false, |         isEdit: false, | ||||||
|         isGroup: false, |  | ||||||
|         confirm: null, |         confirm: null, | ||||||
|         inbound: new Inbound(), |         inbound: new Inbound(), | ||||||
|         dbInbound: new DBInbound(), |         dbInbound: new DBInbound(), | ||||||
|  | @ -61,9 +60,6 @@ | ||||||
|             get isEdit() { |             get isEdit() { | ||||||
|                 return inModal.isEdit; |                 return inModal.isEdit; | ||||||
|             }, |             }, | ||||||
|             get isGroup() { |  | ||||||
|                 return inModal.isGroup; |  | ||||||
|             }, |  | ||||||
|             get client() { |             get client() { | ||||||
|                 return inModal.inbound.clients[0]; |                 return inModal.inbound.clients[0]; | ||||||
|             }, |             }, | ||||||
|  |  | ||||||
|  | @ -145,10 +145,6 @@ | ||||||
|                                                 <a-icon type="rest"></a-icon> |                                                 <a-icon type="rest"></a-icon> | ||||||
|                                                 {{ i18n "pages.inbounds.delDepletedClients" }} |                                                 {{ i18n "pages.inbounds.delDepletedClients" }} | ||||||
|                                             </a-menu-item> |                                             </a-menu-item> | ||||||
|                                             <a-menu-item v-if="subSettings.enable && dbInbounds.length > 0" key="addGroupClient"> |  | ||||||
|                                                 <a-icon type="usergroup-add"></a-icon> |  | ||||||
|                                                 {{ i18n "pages.client.groupAdd"}} |  | ||||||
|                                             </a-menu-item> |  | ||||||
|                                         </a-menu> |                                         </a-menu> | ||||||
|                                     </a-dropdown> |                                     </a-dropdown> | ||||||
|                                 </a-col> |                                 </a-col> | ||||||
|  | @ -744,9 +740,6 @@ | ||||||
|                     case "delDepletedClients": |                     case "delDepletedClients": | ||||||
|                         this.delDepletedClients(-1) |                         this.delDepletedClients(-1) | ||||||
|                         break; |                         break; | ||||||
|                     case "addGroupClient": |  | ||||||
|                         this.openGroupAddClient() |  | ||||||
|                         break; |  | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             clickAction(action, dbInbound) { |             clickAction(action, dbInbound) { | ||||||
|  | @ -890,20 +883,6 @@ | ||||||
| 
 | 
 | ||||||
|                 await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); |                 await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); | ||||||
|             }, |             }, | ||||||
|             openGroupAddClient() { |  | ||||||
|                 clientModal.show({ |  | ||||||
|                     title: '{{ i18n "pages.client.groupAdd"}}', |  | ||||||
|                     okText: '{{ i18n "pages.client.submitAdd"}}', |  | ||||||
|                     dbInbounds: this.dbInbounds, |  | ||||||
|                     confirm: async (clients, dbInboundIds) => { |  | ||||||
|                         clientModal.loading(); |  | ||||||
|                         await this.addGroupClient(clients, dbInboundIds); |  | ||||||
|                         clientModal.close(); |  | ||||||
|                         await this.showQrcode(dbInboundIds[0],clients[0], true) |  | ||||||
|                     }, |  | ||||||
|                     isEdit: false |  | ||||||
|                 }); |  | ||||||
|             }, |  | ||||||
|             openAddClient(dbInboundId) { |             openAddClient(dbInboundId) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|                 clientModal.show({ |                 clientModal.show({ | ||||||
|  | @ -914,7 +893,6 @@ | ||||||
|                         clientModal.loading(); |                         clientModal.loading(); | ||||||
|                         await this.addClient(clients, dbInboundId); |                         await this.addClient(clients, dbInboundId); | ||||||
|                         clientModal.close(); |                         clientModal.close(); | ||||||
|                         await this.showQrcode(dbInboundId,clients) |  | ||||||
|                     }, |                     }, | ||||||
|                     isEdit: false |                     isEdit: false | ||||||
|                 }); |                 }); | ||||||
|  | @ -939,7 +917,6 @@ | ||||||
|                 clientModal.show({ |                 clientModal.show({ | ||||||
|                     title: '{{ i18n "pages.client.edit"}}', |                     title: '{{ i18n "pages.client.edit"}}', | ||||||
|                     okText: '{{ i18n "pages.client.submitEdit"}}', |                     okText: '{{ i18n "pages.client.submitEdit"}}', | ||||||
|                     dbInbounds: this.dbInbounds, |  | ||||||
|                     dbInbound: dbInbound, |                     dbInbound: dbInbound, | ||||||
|                     index: index, |                     index: index, | ||||||
|                     confirm: async (client, dbInboundId, clientId) => { |                     confirm: async (client, dbInboundId, clientId) => { | ||||||
|  | @ -963,41 +940,14 @@ | ||||||
|                     id: dbInboundId, |                     id: dbInboundId, | ||||||
|                     settings: '{"clients": [' + clients.toString() + ']}', |                     settings: '{"clients": [' + clients.toString() + ']}', | ||||||
|                 }; |                 }; | ||||||
| 
 |                 await this.submit(`/panel/inbound/addClient`, data); | ||||||
|                 await this.submit(`/panel/inbound/addClient`, data) |  | ||||||
|             }, |  | ||||||
| 
 |  | ||||||
|             async addGroupClient(clients, dbInboundIds) { |  | ||||||
|                 const data = [] |  | ||||||
|                 dbInboundIds.forEach((dbInboundId, index) => { |  | ||||||
|                     data.push({ |  | ||||||
|                         id: dbInboundId, |  | ||||||
|                         settings: '{"clients": [' + clients[index].toString() + ']}', |  | ||||||
|                     }) |  | ||||||
|                 }) |  | ||||||
| 
 |  | ||||||
|                 await this.submit(`/panel/inbound/addGroupClient`, data, true) |  | ||||||
|             }, |             }, | ||||||
|             async updateClient(client, dbInboundId, clientId) { |             async updateClient(client, dbInboundId, clientId) { | ||||||
|                 if (Array.isArray(client) && Array.isArray(dbInboundId) && Array.isArray(clientId)){ |                 const data = { | ||||||
|                     const data = [] |                     id: dbInboundId, | ||||||
|                     client.forEach((client, index) => { |                     settings: '{"clients": [' + client.toString() + ']}', | ||||||
|                         data.push({ |                 }; | ||||||
|                             clientId: clientId[index], |                 await this.submit(`/panel/inbound/updateClient/${clientId}`, data); | ||||||
|                             inbound: { |  | ||||||
|                                 id: dbInboundId[index], |  | ||||||
|                                 settings: '{"clients": [' + client.toString() + ']}', |  | ||||||
|                             } |  | ||||||
|                         }) |  | ||||||
|                     }) |  | ||||||
|                     await this.submit(`/panel/inbound/updateClients`, data, true); |  | ||||||
|                 }else{ |  | ||||||
|                     const data = { |  | ||||||
|                         id: dbInboundId, |  | ||||||
|                         settings: '{"clients": [' + client.toString() + ']}', |  | ||||||
|                     }; |  | ||||||
|                     await this.submit(`/panel/inbound/updateClient/${clientId}`, data); |  | ||||||
|                 } |  | ||||||
|             }, |             }, | ||||||
|             resetTraffic(dbInboundId) { |             resetTraffic(dbInboundId) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|  | @ -1068,10 +1018,10 @@ | ||||||
|                 } |                 } | ||||||
|                 return newDbInbound; |                 return newDbInbound; | ||||||
|             }, |             }, | ||||||
|             showQrcode(dbInboundId, client, isJustSub = false) { |             showQrcode(dbInboundId, client) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|                 newDbInbound = this.checkFallback(dbInbound); |                 newDbInbound = this.checkFallback(dbInbound); | ||||||
|                 qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client, isJustSub); |                 qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client); | ||||||
|             }, |             }, | ||||||
|             showInfo(dbInboundId, client) { |             showInfo(dbInboundId, client) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|  | @ -1100,8 +1050,8 @@ | ||||||
|                 await this.updateClient(clients[index], dbInboundId, clientId); |                 await this.updateClient(clients[index], dbInboundId, clientId); | ||||||
|                 this.loading(false); |                 this.loading(false); | ||||||
|             }, |             }, | ||||||
|             async submit(url, data, isJson = false) { |             async submit(url, data) { | ||||||
|                 const msg = isJson ? await HttpUtil.postWithModalJson(url, data) : await HttpUtil.postWithModal(url, data); |                 const msg = await HttpUtil.postWithModal(url, data); | ||||||
|                 if (msg.success) { |                 if (msg.success) { | ||||||
|                     await this.getDBInbounds(); |                     await this.getDBInbounds(); | ||||||
|                 } |                 } | ||||||
|  | @ -1243,7 +1193,7 @@ | ||||||
|                     value: '', |                     value: '', | ||||||
|                     okText: '{{ i18n "pages.inbounds.import" }}', |                     okText: '{{ i18n "pages.inbounds.import" }}', | ||||||
|                     confirm: async (dbInboundText) => { |                     confirm: async (dbInboundText) => { | ||||||
|                         await this.submit('/panel/inbound/import', {data: dbInboundText}); |                         await this.submit('/panel/inbound/import', {data: dbInboundText}, promptModal); | ||||||
|                         promptModal.close(); |                         promptModal.close(); | ||||||
|                     }, |                     }, | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "Export Inbound" | "exportInbound" = "Export Inbound" | ||||||
| "import" = "Import" | "import" = "Import" | ||||||
| "importInbound" = "Import an Inbound" | "importInbound" = "Import an Inbound" | ||||||
| "isGroupEdit" = "Group editing" |  | ||||||
| "isGroupEditDesc" = "All clients with the same subscription are edited" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "Add Client" | "add" = "Add Client" | ||||||
| "groupAdd" = "Add subscription user" |  | ||||||
| "edit" = "Edit Client" | "edit" = "Edit Client" | ||||||
| "submitAdd" = "Add Client" | "submitAdd" = "Add Client" | ||||||
| "submitEdit" = "Save Changes" | "submitEdit" = "Save Changes" | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "Exportación entrante" | "exportInbound" = "Exportación entrante" | ||||||
| "import" = "Importar" | "import" = "Importar" | ||||||
| "importInbound" = "Importar un entrante" | "importInbound" = "Importar un entrante" | ||||||
| "isGroupEdit" = "Edición de grupo" |  | ||||||
| "isGroupEditDesc" = "Se editan todos los usuarios con la misma suscripción" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "Agregar Cliente" | "add" = "Agregar Cliente" | ||||||
| "groupAdd" = "Agregar usuario de suscripción" |  | ||||||
| "edit" = "Editar Cliente" | "edit" = "Editar Cliente" | ||||||
| "submitAdd" = "Agregar Cliente" | "submitAdd" = "Agregar Cliente" | ||||||
| "submitEdit" = "Guardar Cambios" | "submitEdit" = "Guardar Cambios" | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "استخراج ورودی" | "exportInbound" = "استخراج ورودی" | ||||||
| "import" = "افزودن" | "import" = "افزودن" | ||||||
| "importInbound" = "افزودن یک ورودی" | "importInbound" = "افزودن یک ورودی" | ||||||
| "isGroupEdit" = "ویرایش گروهی" |  | ||||||
| "isGroupEditDesc" = "تمامی کاربران با سابسکریپشن یکسان ویرایش میشوند" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "کاربر جدید" | "add" = "کاربر جدید" | ||||||
| "groupAdd" = "کاربر جدید سابسکریپشن" |  | ||||||
| "edit" = "ویرایش کاربر" | "edit" = "ویرایش کاربر" | ||||||
| "submitAdd" = "اضافه کردن" | "submitAdd" = "اضافه کردن" | ||||||
| "submitEdit" = "ذخیره تغییرات" | "submitEdit" = "ذخیره تغییرات" | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "Экспорт входящих" | "exportInbound" = "Экспорт входящих" | ||||||
| "import" = "Импортировать" | "import" = "Импортировать" | ||||||
| "importInbound" = "Импортировать входящее сообщение" | "importInbound" = "Импортировать входящее сообщение" | ||||||
| "isGroupEdit" = "Редактирование группы" |  | ||||||
| "isGroupEditDesc" = "Редактируются все пользователи с одной подпиской" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "Добавить пользователя" | "add" = "Добавить пользователя" | ||||||
| "groupAdd" = "Добавить пользователя подписки" |  | ||||||
| "edit" = "Редактировать пользователя" | "edit" = "Редактировать пользователя" | ||||||
| "submitAdd" = "Добавить пользователя" | "submitAdd" = "Добавить пользователя" | ||||||
| "submitEdit" = "Сохранить изменения" | "submitEdit" = "Сохранить изменения" | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "Xuất nhập khẩu" | "exportInbound" = "Xuất nhập khẩu" | ||||||
| "import" = "Nhập" | "import" = "Nhập" | ||||||
| "importInbound" = "Nhập inbound" | "importInbound" = "Nhập inbound" | ||||||
| "isGroupEdit" = "Chỉnh sửa nhóm" |  | ||||||
| "isGroupEditDesc" = "Tất cả người dùng có cùng đăng ký đều được chỉnh sửa" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "Thêm người dùng" | "add" = "Thêm người dùng" | ||||||
| "groupAdd" = "Thêm người dùng đăng ký" |  | ||||||
| "edit" = "Chỉnh sửa người dùng" | "edit" = "Chỉnh sửa người dùng" | ||||||
| "submitAdd" = "Thêm" | "submitAdd" = "Thêm" | ||||||
| "submitEdit" = "Lưu thay đổi" | "submitEdit" = "Lưu thay đổi" | ||||||
|  |  | ||||||
|  | @ -181,12 +181,9 @@ | ||||||
| "exportInbound" = "出口 入境" | "exportInbound" = "出口 入境" | ||||||
| "import"="导入" | "import"="导入" | ||||||
| "importInbound" = "导入入站" | "importInbound" = "导入入站" | ||||||
| "isGroupEdit" = "分组编辑" |  | ||||||
| "isGroupEditDesc" = "编辑具有相同订阅的所有用户" |  | ||||||
| 
 | 
 | ||||||
| [pages.client] | [pages.client] | ||||||
| "add" = "添加客户端" | "add" = "添加客户端" | ||||||
| "groupAdd" = "添加订阅用户" |  | ||||||
| "edit" = "编辑客户端" | "edit" = "编辑客户端" | ||||||
| "submitAdd" = "添加客户端" | "submitAdd" = "添加客户端" | ||||||
| "submitEdit" = "保存修改" | "submitEdit" = "保存修改" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 MHSanaei
						MHSanaei