mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-02 04:52:08 +00:00
[feature] inbounds auto refresh option
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
parent
f5f9347661
commit
d26c21d900
1 changed files with 66 additions and 31 deletions
|
@ -66,28 +66,42 @@
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<a-button type="primary" icon="plus" @click="openAddInbound">{{ i18n "pages.inbounds.addInbound" }}</a-button>
|
<a-row>
|
||||||
<a-dropdown :trigger="['click']">
|
<a-col :xs="24" :sm="24" :lg="12">
|
||||||
<a-button type="primary" icon="menu">{{ i18n "pages.inbounds.generalActions" }}</a-button>
|
<a-button type="primary" icon="plus" @click="openAddInbound">{{ i18n "pages.inbounds.addInbound" }}</a-button>
|
||||||
<a-menu slot="overlay" @click="a => generalActions(a)" :theme="siderDrawer.theme">
|
<a-dropdown :trigger="['click']">
|
||||||
<a-menu-item key="export">
|
<a-button type="primary" icon="menu">{{ i18n "pages.inbounds.generalActions" }}</a-button>
|
||||||
<a-icon type="export"></a-icon>
|
<a-menu slot="overlay" @click="a => generalActions(a)" :theme="siderDrawer.theme">
|
||||||
{{ i18n "pages.inbounds.export" }}
|
<a-menu-item key="export">
|
||||||
</a-menu-item>
|
<a-icon type="export"></a-icon>
|
||||||
<a-menu-item key="resetInbounds">
|
{{ i18n "pages.inbounds.export" }}
|
||||||
<a-icon type="reload"></a-icon>
|
</a-menu-item>
|
||||||
{{ i18n "pages.inbounds.resetAllTraffic" }}
|
<a-menu-item key="resetInbounds">
|
||||||
</a-menu-item>
|
<a-icon type="reload"></a-icon>
|
||||||
<a-menu-item key="resetClients">
|
{{ i18n "pages.inbounds.resetAllTraffic" }}
|
||||||
<a-icon type="file-done"></a-icon>
|
</a-menu-item>
|
||||||
{{ i18n "pages.inbounds.resetAllClientTraffics" }}
|
<a-menu-item key="resetClients">
|
||||||
</a-menu-item>
|
<a-icon type="file-done"></a-icon>
|
||||||
<a-menu-item key="delDepletedClients">
|
{{ i18n "pages.inbounds.resetAllClientTraffics" }}
|
||||||
<a-icon type="rest"></a-icon>
|
</a-menu-item>
|
||||||
{{ i18n "pages.inbounds.delDepletedClients" }}
|
<a-menu-item key="delDepletedClients">
|
||||||
</a-menu-item>
|
<a-icon type="rest"></a-icon>
|
||||||
</a-menu>
|
{{ i18n "pages.inbounds.delDepletedClients" }}
|
||||||
</a-dropdown>
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</a-col>
|
||||||
|
<a-col :xs="24" :sm="24" :lg="12" style="text-align: right;">
|
||||||
|
<a-select v-model="refreshInterval"
|
||||||
|
v-if="isRefreshEnabled"
|
||||||
|
@change="changeRefreshInterval"
|
||||||
|
:dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
|
||||||
|
<a-select-option v-for="key in [5,10,30,60]" :value="key*1000">[[ key ]]s</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-icon type="sync" :spin="isRefreshEnabled"></a-icon>
|
||||||
|
<a-switch v-model="isRefreshEnabled" @change="toggleRefresh"></a-switch>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
<a-input v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus style="max-width: 300px"></a-input>
|
<a-input v-model.lazy="searchKey" placeholder='{{ i18n "search" }}' autofocus style="max-width: 300px"></a-input>
|
||||||
<a-table :columns="columns" :row-key="dbInbound => dbInbound.id"
|
<a-table :columns="columns" :row-key="dbInbound => dbInbound.id"
|
||||||
|
@ -315,25 +329,22 @@
|
||||||
defaultCert: '',
|
defaultCert: '',
|
||||||
defaultKey: '',
|
defaultKey: '',
|
||||||
clientCount: {},
|
clientCount: {},
|
||||||
|
isRefreshEnabled: localStorage.getItem("isRefreshEnabled") === "true" ? true : false,
|
||||||
|
refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning=true) {
|
loading(spinning=true) {
|
||||||
this.spinning = spinning;
|
this.spinning = spinning;
|
||||||
},
|
},
|
||||||
async getDBInbounds() {
|
async getDBInbounds() {
|
||||||
this.loading();
|
|
||||||
const msg = await HttpUtil.post('/xui/inbound/list');
|
const msg = await HttpUtil.post('/xui/inbound/list');
|
||||||
this.loading(false);
|
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setInbounds(msg.obj);
|
this.setInbounds(msg.obj);
|
||||||
this.searchKey = '';
|
|
||||||
},
|
},
|
||||||
async getDefaultSettings() {
|
async getDefaultSettings() {
|
||||||
this.loading();
|
|
||||||
const msg = await HttpUtil.post('/xui/setting/defaultSettings');
|
const msg = await HttpUtil.post('/xui/setting/defaultSettings');
|
||||||
this.loading(false);
|
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -345,17 +356,16 @@
|
||||||
setInbounds(dbInbounds) {
|
setInbounds(dbInbounds) {
|
||||||
this.inbounds.splice(0);
|
this.inbounds.splice(0);
|
||||||
this.dbInbounds.splice(0);
|
this.dbInbounds.splice(0);
|
||||||
this.searchedInbounds.splice(0);
|
|
||||||
for (const inbound of dbInbounds) {
|
for (const inbound of dbInbounds) {
|
||||||
const dbInbound = new DBInbound(inbound);
|
const dbInbound = new DBInbound(inbound);
|
||||||
to_inbound = dbInbound.toInbound()
|
to_inbound = dbInbound.toInbound()
|
||||||
this.inbounds.push(to_inbound);
|
this.inbounds.push(to_inbound);
|
||||||
this.dbInbounds.push(dbInbound);
|
this.dbInbounds.push(dbInbound);
|
||||||
this.searchedInbounds.push(dbInbound);
|
|
||||||
if([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN].includes(inbound.protocol) ){
|
if([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN].includes(inbound.protocol) ){
|
||||||
this.clientCount[inbound.id] = this.getClientCounts(inbound,to_inbound);
|
this.clientCount[inbound.id] = this.getClientCounts(inbound,to_inbound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.searchInbounds(this.searchKey);
|
||||||
},
|
},
|
||||||
getClientCounts(dbInbound,inbound){
|
getClientCounts(dbInbound,inbound){
|
||||||
let clientCount = 0,active = [], deactive = [], depleted = [], expiring = [];
|
let clientCount = 0,active = [], deactive = [], depleted = [], expiring = [];
|
||||||
|
@ -788,6 +798,25 @@
|
||||||
}
|
}
|
||||||
txtModal.show('{{ i18n "pages.inbounds.export"}}',copyText,'All-Inbounds');
|
txtModal.show('{{ i18n "pages.inbounds.export"}}',copyText,'All-Inbounds');
|
||||||
},
|
},
|
||||||
|
async startDataRefreshLoop() {
|
||||||
|
while (this.isRefreshEnabled) {
|
||||||
|
try {
|
||||||
|
await this.getDBInbounds();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
await PromiseUtil.sleep(this.refreshInterval);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleRefresh() {
|
||||||
|
localStorage.setItem("isRefreshEnabled", this.isRefreshEnabled);
|
||||||
|
if (this.isRefreshEnabled) {
|
||||||
|
this.startDataRefreshLoop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeRefreshInterval(){
|
||||||
|
localStorage.setItem("refreshInterval", this.refreshInterval);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
searchKey: debounce(function (newVal) {
|
searchKey: debounce(function (newVal) {
|
||||||
|
@ -795,8 +824,15 @@
|
||||||
}, 500)
|
}, 500)
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.loading();
|
||||||
this.getDefaultSettings();
|
this.getDefaultSettings();
|
||||||
this.getDBInbounds();
|
if (this.isRefreshEnabled) {
|
||||||
|
this.startDataRefreshLoop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.getDBInbounds();
|
||||||
|
}
|
||||||
|
this.loading(false);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
total() {
|
total() {
|
||||||
|
@ -823,7 +859,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{template "inboundModal"}}
|
{{template "inboundModal"}}
|
||||||
|
|
Loading…
Reference in a new issue