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')
-rw-r--r--web/html/xui/client_bulk_modal.html160
-rw-r--r--web/html/xui/client_modal.html133
-rw-r--r--web/html/xui/common_sider.html17
-rw-r--r--web/html/xui/form/client.html110
-rw-r--r--web/html/xui/form/inbound.html3
-rw-r--r--web/html/xui/form/protocol/dokodemo.html5
-rw-r--r--web/html/xui/form/protocol/shadowsocks.html4
-rw-r--r--web/html/xui/form/protocol/socks.html2
-rw-r--r--web/html/xui/form/protocol/trojan.html113
-rw-r--r--web/html/xui/form/protocol/vless.html116
-rw-r--r--web/html/xui/form/protocol/vmess.html109
-rw-r--r--web/html/xui/form/stream/stream_quic.html4
-rw-r--r--web/html/xui/form/stream/stream_settings.html4
-rw-r--r--web/html/xui/form/tls_settings.html30
-rw-r--r--web/html/xui/inbound_info_modal.html119
-rw-r--r--web/html/xui/inbound_modal.html80
-rw-r--r--web/html/xui/inbounds.html245
-rw-r--r--web/html/xui/inbounds_client_row.html (renamed from web/html/xui/inbound_client_table.html)18
-rw-r--r--web/html/xui/index.html28
-rw-r--r--web/html/xui/setting.html122
20 files changed, 482 insertions, 940 deletions
diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html
deleted file mode 100644
index 19fd4b18..00000000
--- a/web/html/xui/client_bulk_modal.html
+++ /dev/null
@@ -1,160 +0,0 @@
-{{define "clientsBulkModal"}}
-<a-modal id="client-bulk-modal" v-model="clientsBulkModal.visible" :title="clientsBulkModal.title" @ok="clientsBulkModal.ok"
- :confirm-loading="clientsBulkModal.confirmLoading" :closable="true" :mask-closable="false"
- :class="siderDrawer.isDarkTheme ? darkClass : ''"
- :ok-text="clientsBulkModal.okText" cancel-text='{{ i18n "close" }}'>
- <a-form layout="inline">
- <a-form-item label='{{ i18n "pages.client.method" }}'>
- <a-select v-model="clientsBulkModal.emailMethod" buttonStyle="solid" style="width: 350px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
- <a-select-option :value="0">Random</a-select-option>
- <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>
- </a-form-item><br />
- <a-form-item v-if="clientsBulkModal.emailMethod>1">
- <span slot="label">{{ i18n "pages.client.first" }}</span>
- <a-input-number v-model="clientsBulkModal.firstNum" :min="1"></a-input-number>
- </a-form-item>
- <a-form-item v-if="clientsBulkModal.emailMethod>1">
- <span slot="label">{{ i18n "pages.client.last" }}</span>
- <a-input-number v-model="clientsBulkModal.lastNum" :min="clientsBulkModal.firstNum"></a-input-number>
- </a-form-item>
- <a-form-item v-if="clientsBulkModal.emailMethod>0">
- <span slot="label">{{ i18n "pages.client.prefix" }}</span>
- <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>
- <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>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
- <a-tooltip>
- <template slot="title">
- 0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </a-tooltip>
- </span>
- <a-input-number v-model="clientsBulkModal.totalGB" :min="0"></a-input-number>
- </a-form-item>
- <a-form-item>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.expireDate" }}</span>
- <a-tooltip>
- <template slot="title">
- <span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </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="clientsBulkModal.expiryTime" style="width: 300px;"></a-date-picker>
- </a-form-item>
- </a-form>
-</a-modal>
-<script>
-
- const clientsBulkModal = {
- visible: false,
- confirmLoading: false,
- title: '',
- okText: '',
- confirm: null,
- dbInbound: new DBInbound(),
- inbound: new Inbound(),
- clients: [],
- quantity: 1,
- totalGB: 0,
- expiryTime: '',
- emailMethod: 0,
- firstNum: 1,
- lastNum: 1,
- emailPrefix: "",
- emailPostfix: "",
- ok() {
- method=clientsBulkModal.emailMethod;
- if(method>1){
- start=clientsBulkModal.firstNum;
- end=clientsBulkModal.lastNum + 1;
- } else {
- start=0;
- end=clientsBulkModal.quantity;
- }
- prefix = (method>0 && clientsBulkModal.emailPrefix.length>0) ? "_" + clientsBulkModal.emailPrefix : "";
- useNum=(method>1);
- postfix = (method>2 && clientsBulkModal.emailPostfix.length>0) ? (method == 4 ? "@" : "") + clientsBulkModal.emailPostfix : "";
- for (let i = start; i < end; i++) {
- newClient = clientsBulkModal.newClient(clientsBulkModal.dbInbound.protocol);
- newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix;
- newClient._totalGB = clientsBulkModal.totalGB;
- newClient._expiryTime = clientsBulkModal.expiryTime;
- clientsBulkModal.clients.push(newClient);
- }
- ObjectUtil.execute(clientsBulkModal.confirm, clientsBulkModal.inbound, clientsBulkModal.dbInbound);
- },
- show({ title='', okText='{{ i18n "sure" }}', dbInbound=null, confirm=(inbound, dbInbound)=>{} }) {
- this.visible = true;
- this.title = title;
- this.okText = okText;
- this.confirm = confirm;
- this.quantity = 1;
- this.totalGB = 0;
- this.expiryTime = '';
- this.emailMethod= 0;
- this.firstNum= 1;
- this.lastNum= 1;
- this.emailPrefix= "";
- this.emailPostfix= "";
-
- this.dbInbound = new DBInbound(dbInbound);
- this.inbound = dbInbound.toInbound();
- this.clients = this.getClients(this.inbound.protocol, this.inbound.settings);
- },
- getClients(protocol, clientSettings) {
- switch(protocol){
- case Protocols.VMESS: return clientSettings.vmesses;
- case Protocols.VLESS: return clientSettings.vlesses;
- case Protocols.TROJAN: return clientSettings.trojans;
- default: return null;
- }
- },
- newClient(protocol) {
- switch (protocol) {
- case Protocols.VMESS: return new Inbound.VmessSettings.Vmess();
- case Protocols.VLESS: return new Inbound.VLESSSettings.VLESS();
- case Protocols.TROJAN: return new Inbound.TrojanSettings.Trojan();
- default: return null;
- }
- },
- close() {
- clientsBulkModal.visible = false;
- clientsBulkModal.loading(false);
- },
- loading(loading) {
- clientsBulkModal.confirmLoading = loading;
- },
- };
-
- const clientsBulkModalApp = new Vue({
- delimiters: ['[[', ']]'],
- el: '#client-bulk-modal',
- data: {
- clientsBulkModal,
- get inbound() {
- return this.clientsBulkModal.inbound;
- },
- },
- });
-</script>
-{{end}} \ No newline at end of file
diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html
deleted file mode 100644
index e4ee8659..00000000
--- a/web/html/xui/client_modal.html
+++ /dev/null
@@ -1,133 +0,0 @@
-{{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 : ''"
- :ok-text="clientModal.okText" cancel-text='{{ i18n "close" }}'>
- {{template "form/client"}}
-</a-modal>
-<script>
-
- const clientModal = {
- visible: false,
- confirmLoading: false,
- title: '',
- okText: '',
- dbInbound: new DBInbound(),
- inbound: new Inbound(),
- clients: [],
- clientStats: [],
- index: null,
- clientIps: null,
- isExpired: false,
- ok() {
- ObjectUtil.execute(clientModal.confirm, clientModal.inbound, clientModal.dbInbound, clientModal.index);
- },
- show({ title='', okText='{{ i18n "sure" }}', index=null, dbInbound=null, confirm=(index, dbInbound)=>{}, isEdit=false }) {
- this.visible = true;
- this.title = title;
- this.okText = okText;
- this.isEdit = isEdit;
- this.dbInbound = new DBInbound(dbInbound);
- this.inbound = dbInbound.toInbound();
- 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;
- if (!isEdit){
- this.addClient(this.inbound.protocol, this.clients);
- }
- this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email);
- this.confirm = confirm;
- },
- getClients(protocol, clientSettings) {
- switch(protocol){
- case Protocols.VMESS: return clientSettings.vmesses;
- case Protocols.VLESS: return clientSettings.vlesses;
- case Protocols.TROJAN: return clientSettings.trojans;
- default: return null;
- }
- },
- addClient(protocol, clients) {
- switch (protocol) {
- case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.Vmess());
- case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS());
- case Protocols.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan());
- default: return null;
- }
- },
- close() {
- clientModal.visible = false;
- clientModal.loading(false);
- },
- loading(loading) {
- clientModal.confirmLoading = loading;
- },
- };
-
- const clientModalApp = new Vue({
- delimiters: ['[[', ']]'],
- el: '#client-modal',
- data: {
- clientModal,
- get inbound() {
- return this.clientModal.inbound;
- },
- get client() {
- return this.clientModal.clients[this.clientModal.index];
- },
- get clientStats() {
- return this.clientModal.clientStats;
- },
- get isEdit() {
- return this.clientModal.isEdit;
- },
- get isTrafficExhausted() {
- if(!clientStats) return false
- if(clientStats.total == 0) return false
- if(clientStats.up + clientStats.down < clientStats.total) return false
- return true
- },
- get isExpiry() {
- return this.clientModal.isExpired
- },
- get statsColor() {
- if(!clientStats) return 'blue'
- if(clientStats.total === 0) return 'blue'
- else if(clientStats.total > 0 && (clientStats.down+clientStats.up) < clientStats.total) return 'cyan'
- else return 'red'
- }
- },
- methods: {
- getNewEmail(client) {
- var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
- var string = '';
- var len = 6 + Math.floor(Math.random() * 5);
- for(var ii=0; ii<len; ii++){
- string += chars[Math.floor(Math.random() * chars.length)];
- }
- client.email = string;
- },
- async getDBClientIps(email,event) {
- const msg = await HttpUtil.post('/xui/inbound/clientIps/'+ email);
- if (!msg.success) {
- return;
- }
- try {
- ips = JSON.parse(msg.obj)
- ips = ips.join(",")
- event.target.value = ips
- } catch (error) {
- // text
- event.target.value = msg.obj
- }
- },
- async clearDBClientIps(email) {
- const msg = await HttpUtil.post('/xui/inbound/clearClientIps/'+ email);
- if (!msg.success) {
- return;
- }
- document.getElementById("clientIPs").value = ""
- },
- },
- });
-</script>
-{{end}}
diff --git a/web/html/xui/common_sider.html b/web/html/xui/common_sider.html
index 13c24c34..66e48d6e 100644
--- a/web/html/xui/common_sider.html
+++ b/web/html/xui/common_sider.html
@@ -13,14 +13,14 @@
</a-menu-item>
<!--<a-menu-item key="{{ .base_path }}xui/clients">-->
<!-- <a-icon type="laptop"></a-icon>-->
-<!-- <span>Client</span>-->
+<!-- <span>client</span>-->
<!--</a-menu-item>-->
<a-sub-menu>
<template slot="title">
<a-icon type="link"></a-icon>
<span>{{ i18n "menu.link"}}</span>
</template>
- <a-menu-item key="https://github.com/mhsanaei/3x-ui/">
+ <a-menu-item key="https://github.com/mhsanaei/3x-ui/">
<a-icon type="github"></a-icon>
<span>Github</span>
</a-menu-item>
@@ -41,7 +41,7 @@
<a-menu :theme="siderDrawer.theme" mode="inline" selected-keys="">
<a-menu-item mode="inline">
<a-icon type="bg-colors"></a-icon>
- <a-switch :default-checked="siderDrawer.isDarkTheme"
+ <a-switch size="small" :default-checked="siderDrawer.isDarkTheme"
checked-children="☀"
un-checked-children="🌙"
@change="siderDrawer.changeTheme()"></a-switch>
@@ -55,12 +55,11 @@
<a-drawer id="sider-drawer" placement="left" :closable="false"
@close="siderDrawer.close()"
:visible="siderDrawer.visible"
- :wrap-class-name="siderDrawer.isDarkTheme ? 'ant-drawer-dark' : ''"
:wrap-style="{ padding: 0 }">
<div class="drawer-handle" @click="siderDrawer.change()" slot="handle">
<a-icon :type="siderDrawer.visible ? 'close' : 'menu-fold'"></a-icon>
</div>
- <a-menu :theme="siderDrawer.theme" mode="inline" selected-keys="">
+ <a-menu mode="inline" selected-keys="">
<a-menu-item mode="inline">
<a-icon type="bg-colors"></a-icon>
<a-switch :default-checked="siderDrawer.isDarkTheme"
@@ -69,17 +68,19 @@
@change="siderDrawer.changeTheme()"></a-switch>
</a-menu-item>
</a-menu>
- <a-menu :theme="siderDrawer.theme" mode="inline" :selected-keys="['{{ .request_uri }}']"
+ <a-menu mode="inline" :selected-keys="['{{ .request_uri }}']"
@click="({key}) => key.startsWith('http') ? window.open(key) : location.href = key">
{{template "menuItems" .}}
</a-menu>
</a-drawer>
<script>
+
+
const darkClass = "ant-card-dark";
const bgDarkStyle = "background-color: #242c3a";
const siderDrawer = {
visible: false,
- collapsed: false,
+ collapsed: false,
isDarkTheme: localStorage.getItem("dark-mode") === 'true' ? true : false,
show() {
this.visible = true;
@@ -89,7 +90,7 @@
},
change() {
this.visible = !this.visible;
- },
+ },
toggleCollapsed() {
this.collapsed = !this.collapsed;
},
diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html
deleted file mode 100644
index fac830e2..00000000
--- a/web/html/xui/form/client.html
+++ /dev/null
@@ -1,110 +0,0 @@
-{{define "form/client"}}
-<a-form layout="inline" v-if="client">
- <template v-if="isEdit">
- <a-tag v-if="isExpiry || isTrafficExhausted" color="red" style="margin-bottom: 10px;display: block;text-align: center;">Account is (Expired|Traffic Ended) And Disabled</a-tag>
- </template>
- <a-form-item>
- <span slot="label">
- Email
- <a-tooltip>
- <template slot="title">
- The Email Must Be Completely Unique
- </template>
- <a-icon type="sync" @click="getNewEmail(client)"></a-icon>
- </a-tooltip>
- </span>
- <a-input v-model.trim="client.email" style="width: 150px;" ></a-input>
- </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>
- <a-form-item label="ID" v-if="inbound.protocol === Protocols.VMESS || inbound.protocol === Protocols.VLESS">
- <a-input v-model.trim="client.id" style="width: 300px;"></a-input>
- </a-form-item>
- <a-form-item label='{{ i18n "additional" }} ID' v-if="inbound.protocol === Protocols.VMESS">
- <a-input type="number" v-model.number="client.alterId" style="width: 70px;"></a-input>
- </a-form-item>
- <a-form-item>
- <span slot="label">
- IP Count Limit
- <a-tooltip>
- <template slot="title">
- Disable inbound if more than entered count (0 for disable limit ip)
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </a-tooltip>
- </span>
- <a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input>
- </a-form-item>
- <a-form-item v-if="client.email && client.limitIp > 0 && isEdit">
- <span slot="label">
- IP Log
- <a-tooltip>
- <template slot="title">
- IPs history Log (before enabling inbound after it has been disabled by IP limit, you should clear the log)
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </a-tooltip>
- <a-tooltip>
- <template slot="title">
- Clear The Log
- </template>
- <span style="color: #FF4D4F">
- <a-icon type="delete" @click="clearDBClientIps(client.email)"></a-icon>
- </span>
- </a-tooltip>
- </span>
- <a-form layout="block">
- <a-textarea id="clientIPs" readonly @click="getDBClientIps(client.email,$event)" placeholder="Click To Get IPs" :auto-size="{ minRows: 2, maxRows: 10 }">
- </a-textarea>
- </a-form>
- </a-form-item>
- <a-form-item v-if="inbound.XTLS" label="Flow">
- <a-select v-model="client.flow" style="width: 150px">
- <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>
- </a-form-item>
- <a-form-item v-else-if="inbound.canEnableTlsFlow()" label="Flow" layout="inline">
- <a-select v-model="client.flow" style="width: 150px">
- <a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
- <a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
- </a-select>
- </a-form-item>
- <a-form-item>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
- <a-tooltip>
- <template slot="title">
- 0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </a-tooltip>
- </span>
- <a-input-number v-model="client._totalGB":min="0" style="width: 70px;"></a-input-number>
- <template v-if="isEdit && clientStats">
- {{ i18n "usage" }}:
- <a-tag :color="statsColor">
- [[ sizeFormat(clientStats.up) ]] /
- [[ sizeFormat(clientStats.down) ]]
- ([[ sizeFormat(clientStats.up + clientStats.down) ]])
- </a-tag>
- </template>
- </a-form-item>
- <a-form-item>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.expireDate" }}</span>
- <a-tooltip>
- <template slot="title">
- <span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </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>
- <a-tag color="red" v-if="isExpiry">Expired</a-tag>
- </a-form-item>
-</a-form>
-{{end}} \ No newline at end of file
diff --git a/web/html/xui/form/inbound.html b/web/html/xui/form/inbound.html
index 74fe1384..1a2e7ca1 100644
--- a/web/html/xui/form/inbound.html
+++ b/web/html/xui/form/inbound.html
@@ -8,7 +8,7 @@
<a-switch v-model="dbInbound.enable"></a-switch>
</a-form-item>
<a-form-item label='{{ i18n "protocol" }}'>
- <a-select v-model="inbound.protocol" style="width: 160px;" :disabled="isEdit" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
+ <a-select v-model="inbound.protocol" style="width: 160px;">
<a-select-option v-for="p in Protocols" :key="p" :value="p">[[ p ]]</a-select-option>
</a-select>
</a-form-item>
@@ -50,7 +50,6 @@
</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="dbInbound._expiryTime" style="width: 300px;"></a-date-picker>
</a-form-item>
</a-form>
diff --git a/web/html/xui/form/protocol/dokodemo.html b/web/html/xui/form/protocol/dokodemo.html
index dbba6b5b..a4dde06d 100644
--- a/web/html/xui/form/protocol/dokodemo.html
+++ b/web/html/xui/form/protocol/dokodemo.html
@@ -7,14 +7,11 @@
<a-input type="number" v-model.number="inbound.settings.port"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.network"}}'>
- <a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
+ <a-select v-model="inbound.settings.network" style="width: 100px;">
<a-select-option value="tcp,udp">tcp+udp</a-select-option>
<a-select-option value="tcp">tcp</a-select-option>
<a-select-option value="udp">udp</a-select-option>
</a-select>
</a-form-item>
- <a-form-item label="FollowRedirect">
- <a-switch v-model="inbound.settings.followRedirect"></a-switch>
- </a-form-item>
</a-form>
{{end}} \ No newline at end of file
diff --git a/web/html/xui/form/protocol/shadowsocks.html b/web/html/xui/form/protocol/shadowsocks.html
index 21d614ae..18bcf727 100644
--- a/web/html/xui/form/protocol/shadowsocks.html
+++ b/web/html/xui/form/protocol/shadowsocks.html
@@ -1,7 +1,7 @@
{{define "form/shadowsocks"}}
<a-form layout="inline">
<a-form-item label='{{ i18n "encryption" }}'>
- <a-select v-model="inbound.settings.method" style="width: 165px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
+ <a-select v-model="inbound.settings.method" style="width: 165px;">
<a-select-option v-for="method in SSMethods" :value="method">[[ method ]]</a-select-option>
</a-select>
</a-form-item>
@@ -9,7 +9,7 @@
<a-input v-model.trim="inbound.settings.password"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.network" }}'>
- <a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
+ <a-select v-model="inbound.settings.network" style="width: 100px;">
<a-select-option value="tcp,udp">tcp+udp</a-select-option>
<a-select-option value="tcp">tcp</a-select-option>
<a-select-option value="udp">udp</a-select-option>
diff --git a/web/html/xui/form/protocol/socks.html b/web/html/xui/form/protocol/socks.html
index 5857d413..35c1c0b5 100644
--- a/web/html/xui/form/protocol/socks.html
+++ b/web/html/xui/form/protocol/socks.html
@@ -1,6 +1,6 @@
{{define "form/socks"}}
<a-form layout="inline">
-<!-- <a-form-item label="Password authentication">-->
+<!-- <a-form-item label="密码认证">-->
<a-form-item label='{{ i18n "password" }}'>
<a-switch :checked="inbound.settings.auth === 'password'"
@change="checked => inbound.settings.auth = checked ? 'password' : 'noauth'"></a-switch>
diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html
index 840ce17d..8061c0f9 100644
--- a/web/html/xui/form/protocol/trojan.html
+++ b/web/html/xui/form/protocol/trojan.html
@@ -1,7 +1,11 @@
{{define "form/trojan"}}
<a-form layout="inline">
-<a-collapse activeKey="0" v-for="(client, index) in inbound.settings.trojans.slice(0,1)" v-if="!isEdit">
- <a-collapse-panel header="{{ i18n "pages.inbounds.client" }}">
+<label style="color: green;">{{ i18n "clients"}}</label>
+<a-collapse activeKey="0" v-for="(trojan, index) in inbound.settings.trojans"
+:key="`trojan-${index}`">
+
+ <a-collapse-panel :class="getHeaderStyle(trojan.email)" :header="getHeaderText(trojan.email)">
+ <a-tag v-if="isExpiry(index) || ((getUpStats(trojan.email) + getDownStats(trojan.email)) > trojan.totalGB && trojan.totalGB != 0)" color="red" style="margin-bottom: 10px;display: block;text-align: center;">Account is (Expired|Traffic Ended) And Disabled</a-tag>
<a-form layout="inline">
<a-form-item>
<span slot="label">
@@ -10,16 +14,18 @@
<template slot="title">
The Email Must Be Completely Unique
</template>
- <a-icon @click="getNewEmail(client)" type="sync"> </a-icon>
+ <!--Renew Svg Icon-->
+ <svg
+ @click="getNewEmail(trojan)"
+ xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="anticon anticon-question-circle" viewBox="0 0 16 16"> <path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/> <path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/> </svg>
</a-tooltip>
</span>
- <a-input v-model.trim="client.email" style="width: 150px;" ></a-input>
+ <a-input v-model.trim="trojan.email" style="width: 150px;"></a-input>
</a-form-item>
- </a-form>
- <a-form-item label="Password">
- <a-input v-model.trim="client.password" style="width: 150px;"></a-input>
- </a-form-item>
- <a-form-item>
+ <a-form-item label="Password" >
+ <a-input v-model.trim="trojan.password" style="width: 150px;"></a-input>
+ </a-form-item>
+ <a-form-item>
<span slot="label">
IP Count Limit
<a-tooltip>
@@ -29,10 +35,34 @@
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</span>
- <a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input>
- </a-form-item>
+ <a-input type="number" v-model.number="trojan.limitIp" min="0" style="width: 70px;"></a-input>
+ </a-form-item>
+ <a-form-item v-if="trojan.email && trojan.limitIp > 0 && isEdit">
+ <span slot="label">
+ IP log
+ <a-tooltip>
+ <template slot="title">
+ IPs history Log (before enabling inbound after it has been disabled by IP limit, you should clear the log)
+ </template>
+ <a-icon type="question-circle" theme="filled"></a-icon>
+ </a-tooltip>
+ <a-tooltip>
+ <template slot="title">
+ clear the log
+ </template>
+ <span style="color: #FF4D4F">
+ <a-icon type="delete" @click="clearDBClientIps(trojan.email,$event)"></a-icon>
+ </span>
+ </a-tooltip>
+ </span>
+ <a-form layout="block">
+ <a-textarea readonly @click="getDBClientIps(trojan.email,$event)" placeholder="Click To Get IPs" :auto-size="{ minRows: 2, maxRows: 10 }">
+ </a-textarea>
+ </a-form>
+ </a-form-item>
+ </a-form>
<a-form-item v-if="inbound.XTLS" label="Flow">
- <a-select v-model="client.flow" style="width: 150px">
+ <a-select v-model="trojan.flow" style="width: 150px">
<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>
@@ -47,7 +77,7 @@
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</span>
- <a-input-number v-model="client._totalGB" :min="0"></a-input-number>
+ <a-input-number v-model="trojan._totalGB" :min="0"></a-input-number>
</a-form-item>
<a-form-item>
<span slot="label">
@@ -60,23 +90,40 @@
</a-tooltip>
</span>
<a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm"
- v-model="client._expiryTime" style="width: 170px;"></a-date-picker>
+ v-model="trojan._expiryTime" style="width: 170px;"></a-date-picker>
</a-form-item>
+ <a-form layout="inline">
+ <a-tooltip v-if="trojan._totalGB > 0">
+ <template slot="title">
+ {{ i18n "pages.inbounds.resetTraffic" }}
+ </template>
+ <span style="color: #FF4D4F">
+ <a-icon type="delete" @click="resetClientTraffic(trojan,$event)"></a-icon>
+ </span>
+ </a-tooltip>
+ <a-tag color="blue">[[ sizeFormat(getUpStats(trojan.email)) ]] / [[ sizeFormat(getDownStats(trojan.email)) ]]</a-tag>
+ <a-tag v-if="trojan._totalGB > 0" color="red">used : [[ sizeFormat(getUpStats(trojan.email) + getDownStats(trojan.email)) ]]</a-tag>
+ <a-tag v-show="inbound.settings.trojans.length > 1" @click="removeClient(index, inbound.settings.trojans)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" width="22" height="22" class="mt-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />