diff options
| author | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-04-09 22:43:18 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-04-09 22:43:18 +0300 |
| commit | e1da43053d23c995bcd6e7267cb20042398cd64f (patch) | |
| tree | 08c4c371ba070ef765ec2be83270ee6032e54774 /web/html | |
| parent | 3bb90cbf2463b31c6a921f7cd75cf32edd3a37f0 (diff) | |
alireza update pack
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
Diffstat (limited to 'web/html')
| -rw-r--r-- | web/html/common/head.html | 1 | ||||
| -rw-r--r-- | web/html/xui/client_bulk_modal.html | 42 | ||||
| -rw-r--r-- | web/html/xui/client_modal.html | 20 | ||||
| -rw-r--r-- | web/html/xui/form/client.html | 25 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/trojan.html | 2 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vless.html | 2 | ||||
| -rw-r--r-- | web/html/xui/form/tls_settings.html | 1 | ||||
| -rw-r--r-- | web/html/xui/inbound_client_table.html | 8 | ||||
| -rw-r--r-- | web/html/xui/inbound_info_modal.html | 54 | ||||
| -rw-r--r-- | web/html/xui/inbound_modal.html | 4 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 245 | ||||
| -rw-r--r-- | web/html/xui/index.html | 41 | ||||
| -rw-r--r-- | web/html/xui/setting.html | 4 |
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
|
