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/xui/inbounds.html')
-rw-r--r--web/html/xui/inbounds.html116
1 files changed, 87 insertions, 29 deletions
diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html
index 8d295121..4cca8aac 100644
--- a/web/html/xui/inbounds.html
+++ b/web/html/xui/inbounds.html
@@ -46,10 +46,10 @@
<div slot="title">
<a-button type="primary" @click="openAddInbound">Add Inbound</a-button>
</div>
-<!-- <a-input v-model="searchKey" placeholder="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"
- :data-source="dbInbounds"
- :loading="spinning" :scroll="{ x: 1500 }"
+ :data-source="searchedInbounds"
+ :loading="spinning" :scroll="{ x: 1300 }"
:pagination="false"
style="margin-top: 20px"
@change="() => getDBInbounds()">
@@ -58,7 +58,7 @@
<a-dropdown :trigger="['click']">
<a @click="e => e.preventDefault()">{{ i18n "pages.inbounds.operate" }}</a>
<a-menu slot="overlay" @click="a => clickAction(a, dbInbound)">
- <a-menu-item v-if="dbInbound.hasLink()" key="qrcode">
+ <a-menu-item v-if="dbInbound.isSS" key="qrcode">
<a-icon type="qrcode"></a-icon>
{{ i18n "qrCode" }}
</a-menu-item>
@@ -88,9 +88,6 @@
</template>
<a-tag v-else color="green">{{ i18n "unlimited" }}</a-tag>
</template>
- <template slot="settings" slot-scope="text, dbInbound">
- <a-button type="link" @click="showInfo(dbInbound)">{{ i18n "check" }}</a-button>
- </template>
<template slot="stream" slot-scope="text, dbInbound, index">
<template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan || dbInbound.isSS">
<a-tag color="green">[[ inbounds[index].stream.network ]]</a-tag>
@@ -115,13 +112,31 @@
</template>
<template slot="expandedRowRender" slot-scope="record">
<a-table
- v-if="(record.protocol === Protocols.VLESS) || (record.protocol === Protocols.VMESS) || (record.protocol === Protocols.TROJAN)"
+ v-if="(record.protocol === Protocols.VLESS) || (record.protocol === Protocols.VMESS)"
:row-key="client => client.id"
:columns="innerColumns"
:data-source="getInboundClients(record)"
:pagination="false"
>
- {{template "form/client_row"}}
+ {{template "client_row"}}
+ </a-table>
+ <a-table
+ v-else-if="record.protocol === Protocols.TROJAN"
+ :row-key="client => client.id"
+ :columns="innerTrojanColumns"
+ :data-source="getInboundClients(record)"
+ :pagination="false"
+ >
+ {{template "client_row"}}
+ </a-table>
+ <a-table
+ v-else
+ :row-key="client => client.id"
+ :columns="innerOneColumns"
+ :data-source="record"
+ :pagination="false"
+ >
+ {{template "client_row"}}
</a-table>
</template>
</a-table>
@@ -152,29 +167,24 @@
}, {
title: '{{ i18n "pages.inbounds.remark" }}',
align: 'center',
- width: 100,
+ width: 60,
dataIndex: "remark",
}, {
title: '{{ i18n "pages.inbounds.protocol" }}',
align: 'center',
- width: 60,
+ width: 40,
scopedSlots: { customRender: 'protocol' },
}, {
title: '{{ i18n "pages.inbounds.port" }}',
align: 'center',
dataIndex: "port",
- width: 60,
+ width: 40,
}, {
title: '{{ i18n "pages.inbounds.traffic" }}↑|↓',
align: 'center',
width: 150,
scopedSlots: { customRender: 'traffic' },
- }, {
- title: '{{ i18n "pages.inbounds.details" }}',
- align: 'center',
- width: 40,
- scopedSlots: { customRender: 'settings' },
- }, {
+ },{
title: '{{ i18n "pages.inbounds.transportConfig" }}',
align: 'center',
width: 60,
@@ -187,10 +197,23 @@
}];
const innerColumns = [
- { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
- { title: '{{ i18n "pages.inbounds.traffic" }}', width: 100, scopedSlots: { customRender: 'traffic' } },
- { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 80, scopedSlots: { customRender: 'expiryTime' } },
- { title: '{{ i18n "pages.inbounds.uid" }}', width: 150, dataIndex: "id" },
+ { title: '', width: 50, scopedSlots: { customRender: 'actions' } },
+ { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
+ { title: '{{ i18n "pages.inbounds.traffic" }}', width: 100, scopedSlots: { customRender: 'traffic' } },
+ { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 80, scopedSlots: { customRender: 'expiryTime' } },
+ { title: 'UID', width: 150, dataIndex: "id" },
+ ];
+
+ const innerTrojanColumns = [
+ { title: '', width: 50, scopedSlots: { customRender: 'actions' } },
+ { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
+ { title: '{{ i18n "pages.inbounds.traffic" }}', width: 100, scopedSlots: { customRender: 'traffic' } },
+ { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 80, scopedSlots: { customRender: 'expiryTime' } },
+ { title: 'Password', width: 150, dataIndex: "password" },
+ ];
+
+ const innerOneColumns = [
+ { title: '', width: 50, scopedSlots: { customRender: 'actions' } },
];
const app = new Vue({
@@ -202,6 +225,7 @@
inbounds: [],
dbInbounds: [],
searchKey: '',
+ searchedInbounds: [],
},
methods: {
loading(spinning=true) {
@@ -219,10 +243,12 @@
setInbounds(dbInbounds) {
this.inbounds.splice(0);
this.dbInbounds.splice(0);
+ this.searchedInbounds.splice(0);
for (const inbound of dbInbounds) {
const dbInbound = new DBInbound(inbound);
this.inbounds.push(dbInbound.toInbound());
this.dbInbounds.push(dbInbound);
+ this.searchedInbounds.push(dbInbound);
}
},
searchInbounds(key) {
@@ -341,12 +367,12 @@
onOk: () => this.submit('/xui/inbound/del/' + dbInbound.id),
});
},
- showQrcode(dbInbound) {
- const link = dbInbound.genLink();
+ showQrcode(dbInbound, clientIndex) {
+ const link = dbInbound.genLink(clientIndex);
qrModal.show('{{ i18n "qrCode"}}', link, dbInbound);
},
- showInfo(dbInbound) {
- infoModal.show(dbInbound);
+ showInfo(dbInbound, index) {
+ infoModal.show(dbInbound, index);
},
switchEnable(dbInbound) {
this.submit(`/xui/inbound/update/${dbInbound.id}`, dbInbound);
@@ -366,6 +392,35 @@
return dbInbound.toInbound().settings.trojans
}
},
+ resetClientTraffic(client,inbound,event) {
+ this.$confirm({
+ title: '{{ i18n "pages.inbounds.resetTraffic"}}',
+ content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
+ okText: '{{ i18n "reset"}}',
+ cancelText: '{{ i18n "cancel"}}',
+ onOk: () => {
+ this.resetClTraffic(client,inbound,event);
+ },
+ });
+ },
+ async resetClTraffic(client,inbound,event) {
+ const msg = await HttpUtil.post('/xui/inbound/resetClientTraffic/'+ client.email);
+ if (!msg.success) {
+ return;
+ }
+ clientStats = inbound.clientStats
+ if(clientStats.length > 0)
+ {
+ for (const key in clientStats) {
+ if (Object.hasOwnProperty.call(clientStats, key)) {
+ if(clientStats[key]['email'] == client.email){
+ clientStats[key]['up'] = 0
+ clientStats[key]['down'] = 0
+ }
+ }
+ }
+ }
+ },
isExpiry(dbInbound, index) {
return dbInbound.toInbound().isExpiry(index)
},
@@ -421,12 +476,15 @@
}
}
}
+ else{
+ return true
+ }
},
},
watch: {
- searchKey(value) {
- this.searchInbounds(value);
- }
+ searchKey: debounce(function (newVal) {
+ this.searchInbounds(newVal);
+ }, 500)
},
mounted() {
this.getDBInbounds();