Explorar el Código

[feature] filter inbound clients

Co-Authored-By: Alireza Ahmadi <[email protected]>
MHSanaei hace 1 año
padre
commit
88fc4f81d4

+ 4 - 4
web/html/xui/form/tls_settings.html

@@ -75,9 +75,9 @@
             <a-radio-group v-model="cert.useFile" button-style="solid">
                 <a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
                 <a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
-                <a-button type="primary" size="small" @click="inbound.stream.tls.addCert()" style="margin: 0 10px">+</a-button>
-                <a-button v-if="inbound.stream.tls.certs.length>1" type="primary" size="small" @click="inbound.stream.tls.removeCert(index)">-</a-button>
             </a-radio-group>
+            <a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.tls.addCert()" style="margin-left: 10px">+</a-button>
+            <a-button v-if="inbound.stream.tls.certs.length>1" type="primary" size="small" @click="inbound.stream.tls.removeCert(index)" style="margin-left: 10px">-</a-button> 
         </a-form-item>
         <template v-if="cert.useFile">
             <a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>
@@ -120,9 +120,9 @@
             <a-radio-group v-model="cert.useFile" button-style="solid">
                 <a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
                 <a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
-                <a-button type="primary" size="small" @click="inbound.stream.xtls.addCert()" style="margin: 0 10px">+</a-button>
-                <a-button v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small" @click="inbound.stream.xtls.removeCert(index)">-</a-button>
             </a-radio-group>
+            <a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()" style="margin-left: 10px">+</a-button>
+            <a-button v-if="inbound.stream.tls.certs.length>1" type="primary" size="small" @click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px">-</a-button> 
         </a-form-item>
         <template v-if="cert.useFile">
             <a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>

+ 52 - 4
web/html/xui/inbounds.html

@@ -105,7 +105,17 @@
                                 </a-col>
                             </a-row>
                         </div>
-                        <a-input v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus style="max-width: 300px"></a-input>
+                        <a-input v-if="!enableFilter" v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus style="max-width: 300px"></a-input>
+                        <a-radio-group v-if="enableFilter" v-model="filterBy" @change="filterInbounds" button-style="solid">
+                            <a-radio-button value="">{{ i18n "none" }}</a-radio-button>
+                            <a-radio-button value="deactive">{{ i18n "disabled" }}</a-radio-button>
+                            <a-radio-button value="depleted">{{ i18n "depleted" }}</a-radio-button>
+                            <a-radio-button value="expiring">{{ i18n "depletingSoon" }}</a-radio-button>
+                        </a-radio-group>
+                        <a-switch v-model="enableFilter"
+                            checked-children='{{ i18n "search" }}' un-checked-children='{{ i18n "filter" }}'
+                            @change="toggleFilter">
+                        </a-switch>
                         <a-table :columns="columns" :row-key="dbInbound => dbInbound.id"
                                  :data-source="searchedInbounds"
                                  :loading="spinning" :scroll="{ x: 1300 }"
@@ -323,6 +333,8 @@
             inbounds: [],
             dbInbounds: [],
             searchKey: '',
+            enableFilter: false,
+            filterBy: '',
             searchedInbounds: [],
             expireDiff: 0,
             trafficDiff: 0,
@@ -331,7 +343,7 @@
             clientCount: {},
             isRefreshEnabled: localStorage.getItem("isRefreshEnabled") === "true" ? true : false,
             refreshing: false,
-            refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000,
+            refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000
         },
         methods: {
             loading(spinning = true) {
@@ -366,11 +378,15 @@
                     to_inbound = dbInbound.toInbound()
                     this.inbounds.push(to_inbound);
                     this.dbInbounds.push(dbInbound);
-                    if ([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN].includes(inbound.protocol)) {
+                    if ([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(inbound.protocol)) {
                         this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound);
                     }
                 }
-                this.searchInbounds(this.searchKey);
+                if(this.enableFilter){
+                    this.filterInbounds();
+                } else {
+                    this.searchInbounds(this.searchKey);
+                }
             },
             getClientCounts(dbInbound, inbound) {
                 let clientCount = 0, active = [], deactive = [], depleted = [], expiring = [];
@@ -428,6 +444,38 @@
                     });
                 }
             },
+            filterInbounds() {
+                if (ObjectUtil.isEmpty(this.filterBy)) {
+                    this.searchedInbounds = this.dbInbounds.slice();
+                } else {
+                    this.searchedInbounds.splice(0, this.searchedInbounds.length);
+                    this.dbInbounds.forEach(inbound => {
+                        const newInbound = new DBInbound(inbound);
+                        const inboundSettings = JSON.parse(inbound.settings);
+                        if (this.clientCount[inbound.id] && this.clientCount[inbound.id].hasOwnProperty(this.filterBy)){
+                            const list = this.clientCount[inbound.id][this.filterBy];
+                            if (list.length > 0) {
+                                const filteredSettings = { "clients": [] };
+                                inboundSettings.clients.forEach(client => {
+                                    if (list.includes(client.email)) {
+                                        filteredSettings.clients.push(client);
+                                    }
+                                });
+                                newInbound.settings = Inbound.Settings.fromJson(inbound.protocol, filteredSettings);
+                                this.searchedInbounds.push(newInbound);
+                            }
+                        }
+                    });
+                }
+            },
+            toggleFilter(){
+                if(this.enableFilter) {
+                    this.searchKey = '';
+                } else {
+                    this.filterBy = '';
+                    this.searchedInbounds = this.dbInbounds.slice();
+                }
+            },
             generalActions(action) {
                 switch (action.key) {
                     case "export":

+ 1 - 1
web/translation/translate.en_US.toml

@@ -11,7 +11,7 @@
 "enable" = "Enable"
 "protocol" = "Protocol"
 "search" = "Search"
-
+"filter" = "Filter"
 "loading" = "Loading"
 "second" = "Second"
 "minute" = "Minute"

+ 1 - 1
web/translation/translate.fa_IR.toml

@@ -11,7 +11,7 @@
 "enable" = "فعال"
 "protocol" = "پروتکل"
 "search" = "جستجو"
-
+"filter" = "فیلتر"
 "loading" = "در حال بروزرسانی..."
 "second" = "ثانیه"
 "minute" = "دقیقه"

+ 1 - 1
web/translation/translate.ru_RU.toml

@@ -11,7 +11,7 @@
 "enable" = "включить"
 "protocol" = "протокол"
 "search" = "поиск"
-
+"filter" = "Фильтр"
 "loading" = "загрузка"
 "second" = "секунда"
 "minute" = "минута"

+ 1 - 1
web/translation/translate.zh_Hans.toml

@@ -11,7 +11,7 @@
 "enable" = "启用"
 "protocol" = "协议"
 "search" = "搜尋"
-
+"filter" = "过滤器"
 "loading" = "加载中"
 "second" = "秒"
 "minute" = "分钟"