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
path: root/web/html
diff options
context:
space:
mode:
authorMHSanaei <ho3ein.sanaei@gmail.com>2023-04-09 22:43:18 +0300
committerMHSanaei <ho3ein.sanaei@gmail.com>2023-04-09 22:43:18 +0300
commite1da43053d23c995bcd6e7267cb20042398cd64f (patch)
tree08c4c371ba070ef765ec2be83270ee6032e54774 /web/html
parent3bb90cbf2463b31c6a921f7cd75cf32edd3a37f0 (diff)
alireza update pack
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
Diffstat (limited to 'web/html')
-rw-r--r--web/html/common/head.html1
-rw-r--r--web/html/xui/client_bulk_modal.html42
-rw-r--r--web/html/xui/client_modal.html20
-rw-r--r--web/html/xui/form/client.html25
-rw-r--r--web/html/xui/form/protocol/trojan.html2
-rw-r--r--web/html/xui/form/protocol/vless.html2
-rw-r--r--web/html/xui/form/tls_settings.html1
-rw-r--r--web/html/xui/inbound_client_table.html8
-rw-r--r--web/html/xui/inbound_info_modal.html54
-rw-r--r--web/html/xui/inbound_modal.html4
-rw-r--r--web/html/xui/inbounds.html245
-rw-r--r--web/html/xui/index.html41
-rw-r--r--web/html/xui/setting.html4
13 files changed, 333 insertions, 116 deletions
diff --git a/web/html/common/head.html b/web/html/common/head.html
index f34ce62f..5e8b1fef 100644
--- a/web/html/common/head.html
+++ b/web/html/common/head.html
@@ -7,6 +7,7 @@
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue@1.7.2/antd.min.css">
<link rel="stylesheet" href="{{ .base_path }}assets/element-ui@2.15.0/theme-chalk/display.css">
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.css?{{ .cur_ver }}">
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<style>
[v-cloak] {
display: none;
diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html
index 2024fa1d..4e282ccd 100644
--- a/web/html/xui/client_bulk_modal.html
+++ b/web/html/xui/client_bulk_modal.html
@@ -10,8 +10,7 @@
<a-select-option :value="1">Random+Prefix</a-select-option>
<a-select-option :value="2">Random+Prefix+Num</a-select-option>
<a-select-option :value="3">Random+Prefix+Num+Postfix</a-select-option>
- <a-select-option :value="4">Random+Prefix+Num@Telegram Username</a-select-option>
- <a-select-option :value="5">Prefix+Num+Postfix [ BE CAREFUL! ]</a-select-option>
+ <a-select-option :value="4">Prefix+Num+Postfix [ BE CAREFUL! ]</a-select-option>
</a-select>
</a-form-item><br />
<a-form-item v-if="clientsBulkModal.emailMethod>1">
@@ -27,15 +26,19 @@
<a-input v-model="clientsBulkModal.emailPrefix" style="width: 120px"></a-input>
</a-form-item>
<a-form-item v-if="clientsBulkModal.emailMethod>2">
- <span slot="label" v-if="clientsBulkModal.emailMethod == 4">tg_uname</span>
- <span slot="label" v-else>{{ i18n "pages.client.postfix" }}</span>
+ <span slot="label">{{ i18n "pages.client.postfix" }}</span>
<a-input v-model="clientsBulkModal.emailPostfix" style="width: 120px"></a-input>
</a-form-item>
-
<a-form-item v-if="clientsBulkModal.emailMethod < 2">
<span slot="label">{{ i18n "pages.client.clientCount" }}</span>
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
</a-form-item>
+ <a-form-item label="Subscription">
+ <a-input v-model.trim="clientsBulkModal.subId"></a-input>
+ </a-form-item>
+ <a-form-item label="Telegram ID">
+ <a-input v-model.trim="clientsBulkModal.tgId"></a-input>
+ </a-form-item>
<a-form-item>
<span slot="label">
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
@@ -48,7 +51,13 @@
</span>
<a-input-number v-model="clientsBulkModal.totalGB" :min="0"></a-input-number>
</a-form-item>
- <a-form-item>
+ <a-form-item label="{{ i18n "pages.client.delayedStart" }}">
+ <a-switch v-model="clientsBulkModal.delayedStart" @click="clientsBulkModal.expiryTime=0"></a-switch>
+ </a-form-item>
+ <a-form-item label="{{ i18n "pages.client.expireDays" }}" v-if="clientsBulkModal.delayedStart">
+ <a-input type="number" v-model.number="delayedExpireDays" :min="0"></a-input>
+ </a-form-item>
+ <a-form-item v-else>
<span slot="label">
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
@@ -83,6 +92,9 @@
lastNum: 1,
emailPrefix: "",
emailPostfix: "",
+ subId: "",
+ tgId: "",
+ delayedStart: false,
ok() {
method=clientsBulkModal.emailMethod;
if(method>1){
@@ -94,11 +106,13 @@
}
prefix = (method>0 && clientsBulkModal.emailPrefix.length>0) ? clientsBulkModal.emailPrefix : "";
useNum=(method>1);
- postfix = (method>2 && clientsBulkModal.emailPostfix.length>0) ? (method == 4 ? "@" : "") + clientsBulkModal.emailPostfix : "";
+ postfix = (method>2 && clientsBulkModal.emailPostfix.length>0) ? clientsBulkModal.emailPostfix : "";
for (let i = start; i < end; i++) {
newClient = clientsBulkModal.newClient(clientsBulkModal.dbInbound.protocol);
- if(method==5) newClient.email = "";
+ if(method==4) newClient.email = "";
newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix;
+ newClient.subId = clientsBulkModal.subId;
+ newClient.tgId = clientsBulkModal.tgId;
newClient._totalGB = clientsBulkModal.totalGB;
newClient._expiryTime = clientsBulkModal.expiryTime;
clientsBulkModal.clients.push(newClient);
@@ -112,16 +126,18 @@
this.confirm = confirm;
this.quantity = 1;
this.totalGB = 0;
- this.expiryTime = '';
+ this.expiryTime = 0;
this.emailMethod= 0;
this.firstNum= 1;
this.lastNum= 1;
this.emailPrefix= "";
this.emailPostfix= "";
-
+ this.subId= "";
+ this.tgId= "";
this.dbInbound = new DBInbound(dbInbound);
this.inbound = dbInbound.toInbound();
this.clients = this.getClients(this.inbound.protocol, this.inbound.settings);
+ this.delayedStart = false;
},
getClients(protocol, clientSettings) {
switch(protocol){
@@ -156,6 +172,12 @@
get inbound() {
return this.clientsBulkModal.inbound;
},
+ get delayedExpireDays() {
+ return this.clientsBulkModal.expiryTime < 0 ? this.clientsBulkModal.expiryTime / -86400000 : 0;
+ },
+ set delayedExpireDays(days){
+ this.clientsBulkModal.expiryTime = -86400000 * days;
+ },
},
});
</script>
diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html
index e4ee8659..d1078f23 100644
--- a/web/html/xui/client_modal.html
+++ b/web/html/xui/client_modal.html
@@ -1,7 +1,7 @@
{{define "clientsModal"}}
<a-modal id="client-modal" v-model="clientModal.visible" :title="clientModal.title" @ok="clientModal.ok"
:confirm-loading="clientModal.confirmLoading" :closable="true" :mask-closable="false"
- :class="siderDrawer.isDarkTheme ? darkClass : ''"
+ :class="siderDrawer.isDarkTheme ? darkClass : ''"
:ok-text="clientModal.okText" cancel-text='{{ i18n "close" }}'>
{{template "form/client"}}
</a-modal>
@@ -19,6 +19,7 @@
index: null,
clientIps: null,
isExpired: false,
+ delayedStart: false,
ok() {
ObjectUtil.execute(clientModal.confirm, clientModal.inbound, clientModal.dbInbound, clientModal.index);
},
@@ -32,8 +33,13 @@
this.clients = this.getClients(this.inbound.protocol, this.inbound.settings);
this.index = index === null ? this.clients.length : index;
this.isExpired = isEdit ? this.inbound.isExpiry(this.index) : false;
+ this.delayedStart = false;
if (!isEdit){
this.addClient(this.inbound.protocol, this.clients);
+ } else {
+ if (this.clients[index].expiryTime < 0){
+ this.delayedStart = true;
+ }
}
this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email);
this.confirm = confirm;
@@ -82,7 +88,7 @@
},
get isTrafficExhausted() {
if(!clientStats) return false
- if(clientStats.total == 0) return false
+ if(clientStats.total <= 0) return false
if(clientStats.up + clientStats.down < clientStats.total) return false
return true
},
@@ -91,10 +97,16 @@
},
get statsColor() {
if(!clientStats) return 'blue'
- if(clientStats.total === 0) return 'blue'
+ if(clientStats.total <= 0) return 'blue'
else if(clientStats.total > 0 && (clientStats.down+clientStats.up) < clientStats.total) return 'cyan'
else return 'red'
- }
+ },
+ get delayedExpireDays() {
+ return this.client && this.client.expiryTime < 0 ? this.client.expiryTime / -86400000 : 0;
+ },
+ set delayedExpireDays(days){
+ this.client.expiryTime = -86400000 * days;
+ },
},
methods: {
getNewEmail(client) {
diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html
index 288fb0ef..3f91c8e8 100644
--- a/web/html/xui/form/client.html
+++ b/web/html/xui/form/client.html
@@ -15,6 +15,9 @@
</span>
<a-input v-model.trim="client.email" style="width: 150px;" ></a-input>
</a-form-item>
+ <a-form-item label="{{ i18n "pages.inbounds.enable" }}">
+ <a-switch v-model="client.enable"></a-switch>
+ </a-form-item>
<a-form-item label="Password" v-if="inbound.protocol === Protocols.TROJAN">
<a-input v-model.trim="client.password" style="width: 150px;" ></a-input>
</a-form-item>
@@ -59,8 +62,14 @@
</a-textarea>
</a-form>
</a-form-item>
+ <a-form-item label="Subscription" v-if="client.email">
+ <a-input v-model.trim="client.subId"></a-input>
+ </a-form-item>
+ <a-form-item label="Telegram Username" v-if="client.email">
+ <a-input v-model.trim="client.tgId"></a-input>
+ </a-form-item>
<a-form-item v-if="inbound.XTLS" label="Flow">
- <a-select v-model="client.flow" style="width: 150px">
+ <a-select v-model="client.flow" style="width: 150px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<a-select-option value="">{{ i18n "none" }}</a-select-option>
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
</a-select>
@@ -83,7 +92,7 @@
</span>
<a-input-number v-model="client._totalGB":min="0" style="width: 70px;"></a-input-number>
<template v-if="isEdit && clientStats">
- {{ i18n "usage" }}:
+ <span>{{ i18n "usage" }}:</span>
<a-tag :color="statsColor">
[[ sizeFormat(clientStats.up) ]] /
[[ sizeFormat(clientStats.down) ]]
@@ -91,7 +100,13 @@
</a-tag>
</template>
</a-form-item>
- <a-form-item>
+ <a-form-item label="{{ i18n "pages.client.delayedStart" }}">
+ <a-switch v-model="clientModal.delayedStart" @click="client._expiryTime=0"></a-switch>
+ </a-form-item>
+ <a-form-item label="{{ i18n "pages.client.expireDays" }}" v-if="clientModal.delayedStart">
+ <a-input type="number" v-model.number="delayedExpireDays" :min="0"></a-input>
+ </a-form-item>
+ <a-form-item v-else>
<span slot="label">
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
@@ -102,8 +117,8 @@
</a-tooltip>
</span>
<a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm"
- :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"
- v-model="client._expiryTime" style="width: 170px;"></a-date-picker>
+ :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"
+ v-model="client._expiryTime" style="width: 170px;"></a-date-picker>
<a-tag color="red" v-if="isExpiry">Expired</a-tag>
</a-form-item>
</a-form>
diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html
index c0694d25..158b64af 100644
--- a/web/html/xui/form/protocol/trojan.html
+++ b/web/html/xui/form/protocol/trojan.html
@@ -76,7 +76,7 @@
</table>
</a-collapse-panel>
</a-collapse>
-<template v-if="inbound.isTcp && (inbound.tls || inbound.xtls)">
+<template v-if="inbound.isTcp">
<a-form layout="inline">
<a-form-item label="Fallbacks">
<a-row>
diff --git a/web/html/xui/form/protocol/vless.html b/web/html/xui/form/protocol/vless.html
index 7dfc5402..03069c29 100644
--- a/web/html/xui/form/protocol/vless.html
+++ b/web/html/xui/form/protocol/vless.html
@@ -82,7 +82,7 @@
</table>
</a-collapse-panel>
</a-collapse>
-<template v-if="inbound.isTcp && (inbound.tls || inbound.xtls)">
+<template v-if="inbound.isTcp">
<a-form layout="inline">
<a-form-item label="Fallbacks">
<a-row>
diff --git a/web/html/xui/form/tls_settings.html b/web/html/xui/form/tls_settings.html
index acb0a815..c083aa20 100644
--- a/web/html/xui/form/tls_settings.html
+++ b/web/html/xui/form/tls_settings.html
@@ -61,6 +61,7 @@
<a-form-item label='{{ i18n "pages.inbounds.keyPath" }}'>
<a-input v-model.trim="inbound.stream.tls.certs[0].keyFile" style="width:300px;"></a-input>
</a-form-item>
+ <a-button @click="setDefaultCertData">{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
</template>
<template v-else>
<a-form-item label='{{ i18n "pages.inbounds.publicKeyContent" }}'>
diff --git a/web/html/xui/inbound_client_table.html b/web/html/xui/inbound_client_table.html
index 4d7bd932..6100cd9b 100644
--- a/web/html/xui/inbound_client_table.html
+++ b/web/html/xui/inbound_client_table.html
@@ -21,9 +21,12 @@
<a-icon style="font-size: 24px;" type="delete" v-if="isRemovable(record.id)" @click="delClient(record.id,client)"></a-icon>
</a-tooltip>
</template>
+<template slot="enable" slot-scope="text, client, index">
+ <a-switch v-model="client.enable" @change="switchEnableClient(record.id,client)"></a-switch>
+</template>
<template slot="client" slot-scope="text, client">
[[ client.email ]]
- <a-tag v-if="!isClientEnabled(record, client.email)" color="red">{{ i18n "disabled" }}</a-tag>
+ <a-tag v-if="!isClientEnabled(record, client.email)" color="red">{{ i18n "depleted" }}</a-tag>
</template>
<template slot="traffic" slot-scope="text, client">
<a-tag color="blue">[[ sizeFormat(getUpStats(record, client.email)) ]] / [[ sizeFormat(getDownStats(record, client.email)) ]]</a-tag>
@@ -34,11 +37,12 @@
<a-tag v-else color="green">{{ i18n "indefinite" }}</a-tag>
</template>
<template slot="expiryTime" slot-scope="text, client, index">
- <template v-if="client._expiryTime > 0">
+ <template v-if="client.expiryTime > 0">
<a-tag :color="isExpiry(record, index)? 'red' : 'blue'">
[[ DateUtil.formatMillis(client._expiryTime) ]]
</a-tag>
</template>
+ <a-tag v-else-if="client.expiryTime < 0" color="cyan">[[ client._expiryTime ]] {{ i18n "pages.client.days" }}</a-tag>
<a-tag v-else color="green">{{ i18n "indefinite" }}</a-tag>
</template>
{{end}} \ No newline at end of file
diff --git a/web/html/xui/inbound_info_modal.html b/web/html/xui/inbound_info_modal.html
index 6de729f9..1ba15b08 100644
--- a/web/html/xui/inbound_info_modal.html
+++ b/web/html/xui/inbound_info_modal.html
@@ -59,13 +59,25 @@
</table>
<template v-if="infoModal.clientSettings">
<a-divider>{{ i18n "pages.inbounds.client" }}</a-divider>
- <table style="margin-bottom: 10px;">
+ <table style="margin-bottom: 10px;">
<tr v-for="col,index in Object.keys(infoModal.clientSettings).slice(0, 3)">
<td>[[ col ]]</td>
- <td><a-tag color="green">[[ infoModal.clientSettings[col] ]]</a-tag></td>
- </table>
+ <td><a-tag color="green">[[ infoModal.clientSettings[col] ]]</a-tag></td>
+ </tr>
+ <tr>
+ <td>{{ i18n "status" }}</td>
+ <td>
+ <a-tag v-if="isEnable" color="blue">{{ i18n "enabled" }}</a-tag>
+ <a-tag v-else color="red">{{ i18n "disabled" }}</a-tag>
+ <a-tag v-if="!isActive" color="red">{{ i18n "depleted" }}</a-tag>
+ </td>
+ </tr>
+ </table>
<table style="margin-bottom: 10px; width: 100%;">
- <tr><th>{{ i18n "usage" }}</th><th>{{ i18n "pages.inbounds.totalFlow" }}</th><th>{{ i18n "pages.inbounds.expireDate" }}</th><th>{{ i18n "enable" }}</th></tr>
+ <tr>
+ <th>{{ i18n "usage" }}</th>
+ <th>{{ i18n "pages.inbounds.totalFlow" }}</th>
+ <th>{{ i18n "pages.inbounds.expireDate" }}</th>
<tr>
<td>
<a-tag v-if="infoModal.clientStats" :color="statsColor(infoModal.clientStats)">
@@ -84,12 +96,19 @@
[[ DateUtil.formatMillis(infoModal.clientSettings.expiryTime) ]]
</a-tag>
</template>
+ <a-tag v-else-if="infoModal.clientSettings.expiryTime < 0" color="cyan">[[ infoModal.clientSettings.expiryTime / -86400000 ]] {{ i18n "pages.client.days" }}</a-tag>
<a-tag v-else color="green">{{ i18n "indefinite" }}</a-tag>
</td>
- <td>
- <a-tag v-if="isEnable" color="blue">{{ i18n "enabled" }}</a-tag>
- <a-tag v-else color="red">{{ i18n "disabled" }}</a-tag>
- </td>
+ </tr>
+ </table>
+ <table v-if="infoModal.clientSettings.subId + infoModal.clientSettings.tgId" style="margin-bottom: 10px;">
+ <tr v-if="infoModal.clientSettings.subId">
+ <td>Subscription link</td>
+ <td><a :href="[[ subBase + infoModal.clientSettings.subId ]]" target="_blank">[[ subBase + infoModal.clientSettings.subId ]]</a></td>
+ </tr>
+ <tr v-if="infoModal.clientSettings.tgId">
+ <td>Telegram Username</td>
+ <td><a :href="[[ tgBase + infoModal.clientSettings.tgId ]]" target="_blank">@[[ infoModal.clientSettings.tgId ]]</a></td>
</tr>
</table>
</template>
@@ -160,13 +179,12 @@
</div>
</a-modal>
<script>
-
const infoModal = {
visible: false,
inbound: new Inbound(),
dbInbound: new DBInbound(),
settings: null,
- clientSettings: new Inbound.Settings(),
+ clientSettings: null,
clientStats: [],
upStats: 0,
downStats: 0,
@@ -209,12 +227,24 @@
get inbound() {
return this.infoModal.inbound;
},
- get isEnable() {
+ get isActive() {
if(infoModal.clientStats){
return infoModal.clientStats.enable;
}
return infoModal.dbInbound.isEnable;
- }
+ },
+ get isEnable() {
+ if(infoModal.clientSettings){
+ return infoModal.clientSettings.enable;
+ }
+ return infoModal.dbInbound.isEnable;
+ },
+ get subBase() {
+ return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port:"") + "/sub/";
+ },
+ get tgBase() {
+ return "https://t.me/"
+ },
},
methods: {
copyTextToClipboard(elmentId,content) {
diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html
index c70b59fd..6b140abc 100644
--- a/web/html/xui/inbound_modal.html
+++ b/web/html/xui/inbound_modal.html
@@ -96,6 +96,10 @@
clientStats = this.dbInbound.clientStats ? this.dbInbound.clientStats.find(stats => stats.email === email) : null
return clientStats ? clientStats['enable'] : true
},
+ setDefaultCertData(){
+ inModal.inbound.stream.tls.certs[0].certFile = app.defaultCert;
+ inModal.inbound.stream.tls.certs[0].keyFile = app.defaultKey;
+ },
getNewEmail(client) {
var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
var string = '';
diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html
index 90250869..728e62a0 100644
--- a/web/html/xui/inbounds.html
+++ b/web/html/xui/inbounds.html
@@ -41,8 +41,24 @@
<a-col :xs="24" :sm="24" :lg="12">
{{ i18n "clients" }}:
<a-tag color="green">[[ total.clients ]]</a-tag>
- <a-tag color="blue">{{ i18n "enabled" }} [[ total.active ]]</a-tag>
- <a-tag color="red">{{ i18n "disabled" }} [[ total.deactive ]]</a-tag>
+ <a-popover title="{{ i18n "disabled" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in total.deactive">[[ clientEmail ]]</p>
+ </template>
+ <a-tag v-if="total.deactive.length">[[ total.deactive.length ]]</a-tag>
+ </a-popover>
+ <a-popover title="{{ i18n "depleted" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in total.depleted">[[ clientEmail ]]</p>
+ </template>
+ <a-tag color="red" v-if="total.depleted.length">[[ total.depleted.length ]]</a-tag>
+ </a-popover>
+ <a-popover title="{{ i18n "depletingSoon" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in total.expiring">[[ clientEmail ]]</p>
+ </template>
+ <a-tag color="orange" v-if="total.expiring.length">[[ total.expiring.length ]]</a-tag>
+ </a-popover>
</a-col>
</a-row>
</a-card>
@@ -52,7 +68,7 @@
<div slot="title">
<a-button type="primary" icon="plus" @click="openAddInbound">{{ i18n "pages.inbounds.addInbound" }}</a-button>
<a-button type="primary" icon="export" @click="exportAllLinks">{{ i18n "pages.inbounds.export" }}</a-button>
- <a-button type="primary" icon="reload" @click="resetAllTraffic">{{ i18n "pages.inbounds.resetAllTraffic" }}</a-button>
+ <a-button type="primary" icon="reload" @click="resetAllTraffic">{{ i18n "pages.inbounds.resetAllTraffic" }}</a-button>
</div>
<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"
@@ -64,8 +80,8 @@
<template slot="action" slot-scope="text, dbInbound">
<a-icon type="edit" style="font-size: 25px" @click="openEditInbound(dbInbound.id);"></a-icon>
<a-dropdown :trigger="['click']">
- <a @click="e => e.preventDefault()">{{ i18n "pages.inbounds.operate" }}</a>
- <a-menu slot="overlay" @click="a => clickAction(a, dbInbound)" :theme="siderDrawer.theme" style="border: 1px solid rgba(255, 255, 255, 0.65);">
+ <a @click="e => e.preventDefault()">{{ i18n "pages.inbounds.operate" }}</a>
+ <a-menu slot="overlay" @click="a => clickAction(a, dbInbound)" :theme="siderDrawer.theme">
<a-menu-item v-if="dbInbound.isSS" key="qrcode">
<a-icon type="qrcode"></a-icon>
{{ i18n "qrCode" }}
@@ -76,13 +92,17 @@
</a-menu-item>
<template v-if="dbInbound.isTrojan || dbInbound.isVLess || dbInbound.isVMess">
<a-menu-item key="addClient">
- <a-icon type="user"></a-icon>
+ <a-icon type="user-add"></a-icon>
{{ i18n "pages.client.add"}}
</a-menu-item>
<a-menu-item key="addBulkClient">
- <a-icon type="team"></a-icon>
+ <a-icon type="usergroup-add"></a-icon>
{{ i18n "pages.client.bulk"}}
</a-menu-item>
+ <a-menu-item key="resetClients">
+ <a-icon type="file-done"></a-icon>
+ {{ i18n "pages.inbounds.resetAllClientTraffics"}}
+ </a-menu-item>
<a-menu-item key="export">
<a-icon type="export"></a-icon>
{{ i18n "pages.inbounds.export"}}
@@ -97,7 +117,7 @@
<a-menu-item key="resetTraffic">
<a-icon type="retweet"></a-icon> {{ i18n "pages.inbounds.resetTraffic" }}
</a-menu-item>
- <a-menu-item key="clone">
+ <a-menu-item key="clone">
<a-icon type="block"></a-icon> {{ i18n "pages.inbounds.Clone"}}
</a-menu-item>
<a-menu-item key="delete">
@@ -109,7 +129,35 @@
</a-dropdown>
</template>
<template slot="protocol" slot-scope="text, dbInbound">
- <a-tag color="blue">[[ dbInbound.protocol ]]</a-tag>
+ <a-tag style="margin:0;" color="blue">[[ dbInbound.protocol ]]</a-tag>
+ <template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan || dbInbound.isSS">
+ <a-tag style="margin:0;" color="green">[[ dbInbound.toInbound().stream.network ]]</a-tag>
+ <a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isTls" color="cyan">TLS</a-tag>
+ <a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isXTLS" color="cyan">XTLS</a-tag>
+ </template>
+ </template>
+ <template slot="clients" slot-scope="text, dbInbound">
+ <template v-if="clientCount[dbInbound.id]">
+ <a-tag style="margin:0;" color="green">[[ clientCount[dbInbound.id].clients ]]</a-tag>
+ <a-popover title="{{ i18n "disabled" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in clientCount[dbInbound.id].deactive">[[ clientEmail ]]</p>
+ </template>
+ <a-tag style="margin:0; padding: 0 2px;" v-if="clientCount[dbInbound.id].deactive.length">[[ clientCount[dbInbound.id].deactive.length ]]</a-tag>
+ </a-popover>
+ <a-popover title="{{ i18n "depleted" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in clientCount[dbInbound.id].depleted">[[ clientEmail ]]</p>
+ </template>
+ <a-tag style="margin:0; padding: 0 2px;" color="red" v-if="clientCount[dbInbound.id].depleted.length">[[ clientCount[dbInbound.id].depleted.length ]]</a-tag>
+ </a-popover>
+ <a-popover title="{{ i18n "depletingSoon" }}" :overlay-class-name="siderDrawer.isDarkTheme ? 'ant-dark' : ''">
+ <template slot="content">
+ <p v-for="clientEmail in clientCount[dbInbound.id].expiring">[[ clientEmail ]]</p>
+ </template>
+ <a-tag style="margin:0; padding: 0 2px;" color="orange" v-if="clientCount[dbInbound.id].expiring.length">[[ clientCount[dbInbound.id].expiring.length ]]</a-tag>
+ </a-popover>
+ </template>
</template>
<template slot="traffic" slot-scope="text, dbInbound">
<a-tag color="blue">[[ sizeFormat(dbInbound.up) ]] / [[ sizeFormat(dbInbound.down) ]]</a-tag>
@@ -119,14 +167,6 @@
</template>
<a-tag v-else color="green">{{ i18n "unlimited" }}</a-tag>
</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>
- <a-tag v-if="inbounds[index].stream.isTls" color="blue">tls</a-tag>
- <a-tag v-if="inbounds[index].stream.isXTls" color="blue">xtls</a-tag>
- </template>
- <template v-else>{{ i18n "none" }}</template>
- </template>
<template slot="enable" slot-scope="text, dbInbound">
<a-switch v-model="dbInbound.enable" @change="switchEnable(dbInbound.id)"></a-switch>
</template>
@@ -192,26 +232,26 @@
width: 80,
dataIndex: "remark",
}, {
- title: '{{ i18n "pages.inbounds.protocol" }}',
- align: 'center',
- width: 50,
- scopedSlots: { customRender: 'protocol' },
- }, {
title: '{{ i18n "pages.inbounds.port" }}',
align: 'center',
dataIndex: "port",
width: 40,
}, {
+ title: '{{ i18n "pages.inbounds.protocol" }}',
+ align: 'left',
+ width: 70,
+ scopedSlots: { customRender: 'protocol' },
+ }, {
+ title: '{{ i18n "clients" }}',
+ align: 'left',
+ width: 50,
+ scopedSlots: { customRender: 'clients' },
+ }, {
title: '{{ i18n "pages.inbounds.traffic" }}↑|↓',
align: 'center',
- width: 150,
+ width: 120,
scopedSlots: { customRender: 'traffic' },
}, {
- title: '{{ i18n "pages.inbounds.transportConfig" }}',
- align: 'center',
- width: 60,
- scopedSlots: { customRender: 'stream' },
- }, {
title: '{{ i18n "pages.inbounds.expireDate" }}',
align: 'center',
width: 80,
@@ -220,15 +260,18 @@
const innerColumns = [
{ title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } },
- { title: '{{ i18n "pages.inbounds.client" }}', width: 60, scopedSlots: { customRender: 'client' } },
- { title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 100, scopedSlots: { customRender: 'traffic' } },
+ { title: '{{ i18n "pages.inbounds.enable" }}', width: 30, scopedSlots: { customRender: 'enable' } },
+ { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
+ { title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 70, scopedSlots: { customRender: 'traffic' } },
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
- { title: 'UID', width: 150, dataIndex: "id" },
+ { title: 'UID', width: 120, dataIndex: "id" },
];
+
const innerTrojanColumns = [
{ title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } },
- { title: '{{ i18n "pages.inbounds.client" }}', width: 60, scopedSlots: { customRender: 'client' } },
- { title: '{{ i18n "pa