diff options
| author | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-03-17 19:07:49 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-03-17 19:07:49 +0300 |
| commit | 96786c94189f3d2f3f04c1915529c786228bdf42 (patch) | |
| tree | 879085e09a3cd485f3246f46be907fe77eb84a1a /web/html/xui | |
| parent | bc56e637376142c370c31b17558fc3778a863bd2 (diff) | |
alireza
Diffstat (limited to 'web/html/xui')
| -rw-r--r-- | web/html/xui/client_bulk_modal.html | 160 | ||||
| -rw-r--r-- | web/html/xui/client_modal.html | 133 | ||||
| -rw-r--r-- | web/html/xui/common_sider.html | 15 | ||||
| -rw-r--r-- | web/html/xui/form/client.html | 110 | ||||
| -rw-r--r-- | web/html/xui/form/inbound.html | 3 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/dokodemo.html | 5 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/shadowsocks.html | 4 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/socks.html | 2 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/trojan.html | 103 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vless.html | 99 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vmess.html | 104 | ||||
| -rw-r--r-- | web/html/xui/form/stream/stream_quic.html | 4 | ||||
| -rw-r--r-- | web/html/xui/form/stream/stream_settings.html | 4 | ||||
| -rw-r--r-- | web/html/xui/form/tls_settings.html | 20 | ||||
| -rw-r--r-- | web/html/xui/inbound_client_table.html | 44 | ||||
| -rw-r--r-- | web/html/xui/inbound_info_modal.html | 119 | ||||
| -rw-r--r-- | web/html/xui/inbound_modal.html | 80 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 241 | ||||
| -rw-r--r-- | web/html/xui/index.html | 18 | ||||
| -rw-r--r-- | web/html/xui/setting.html | 120 |
20 files changed, 977 insertions, 411 deletions
diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html new file mode 100644 index 00000000..19fd4b18 --- /dev/null +++ b/web/html/xui/client_bulk_modal.html @@ -0,0 +1,160 @@ +{{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 new file mode 100644 index 00000000..17381a88 --- /dev/null +++ b/web/html/xui/client_modal.html @@ -0,0 +1,133 @@ +{{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,event) { + const msg = await HttpUtil.post('/xui/inbound/clearClientIps/'+ email); + if (!msg.success) { + return; + } + event.target.value = "" + }, + }, + }); +</script> +{{end}} diff --git a/web/html/xui/common_sider.html b/web/html/xui/common_sider.html index 9de00175..13c24c34 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> @@ -55,11 +55,12 @@ <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 mode="inline" selected-keys=""> + <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" @@ -68,19 +69,17 @@ @change="siderDrawer.changeTheme()"></a-switch> </a-menu-item> </a-menu> - <a-menu mode="inline" :selected-keys="['{{ .request_uri }}']" + <a-menu :theme="siderDrawer.theme" 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; @@ -90,7 +89,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 new file mode 100644 index 00000000..586f4fd4 --- /dev/null +++ b/web/html/xui/form/client.html @@ -0,0 +1,110 @@ +{{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,$event)"></a-icon> + </span> + </a-tooltip> + </span> + <a-form layout="block"> + <a-textarea 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 1a2e7ca1..74fe1384 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;"> + <a-select v-model="inbound.protocol" style="width: 160px;" :disabled="isEdit" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <a-select-option v-for="p in Protocols" :key="p" :value="p">[[ p ]]</a-select-option> </a-select> </a-form-item> @@ -50,6 +50,7 @@ </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 a4dde06d..dbba6b5b 100644 --- a/web/html/xui/form/protocol/dokodemo.html +++ b/web/html/xui/form/protocol/dokodemo.html @@ -7,11 +7,14 @@ <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;"> + <a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <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 18bcf727..21d614ae 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;"> + <a-select v-model="inbound.settings.method" style="width: 165px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <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;"> + <a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <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 35c1c0b5..5857d413 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="密码认证">--> +<!-- <a-form-item label="Password authentication">--> <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 3127e4c5..e1d82572 100644 --- a/web/html/xui/form/protocol/trojan.html +++ b/web/html/xui/form/protocol/trojan.html @@ -1,11 +1,7 @@ {{define "form/trojan"}} <a-form layout="inline"> -<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-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" }}"> <a-form layout="inline"> <a-form-item> <span slot="label"> @@ -14,18 +10,16 @@ <template slot="title"> The Email Must Be Completely Unique </template> - <!--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-icon @click="getNewEmail(client)" type="sync"> </a-icon> </a-tooltip> </span> - <a-input v-model.trim="trojan.email" style="width: 150px;"></a-input> + <a-input v-model.trim="client.email" style="width: 150px;" ></a-input> </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> + </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> <span slot="label"> IP Count Limit <a-tooltip> @@ -35,9 +29,9 @@ <a-icon type="question-circle" theme="filled"></a-icon> </a-tooltip> </span> - <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"> + <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> @@ -51,22 +45,26 @@ clear the log </template> <span style="color: #FF4D4F"> - <a-icon type="delete" @click="clearDBClientIps(trojan.email,$event)"></a-icon> + <a-icon type="delete" @click="clearDBClientIps(client.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 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> - <a-form-item v-if="inbound.XTLS" label="Flow"> - <a-select v-model="trojan.flow" style="width: 150px"> + </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-if="inbound.tls" label="uTLS" layout="inline"> + <a-select v-model="inbound.settings.trojans[index].fingerprint" label="uTLS" style="width: 150px"> + <a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option> + </a-select> + </a-form-item> <a-form-item> <span slot="label"> <span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB) @@ -77,7 +75,7 @@ <a-icon type="question-circle" theme="filled"></a-icon> </a-tooltip> </span> - <a-input-number v-model="trojan._totalGB" :min="0"></a-input-number> + <a-input-number v-model="client._totalGB" :min="0"></a-input-number> </a-form-item> <a-form-item> <span slot="label"> @@ -90,39 +88,22 @@ </a-tooltip> </span> <a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm" - v-model="trojan._expiryTime" style="width: 170px;"></a-date-picker> + v-model="client._expiryTime" style="width: 170px;"></a-date-picker> </a-form-item> - <a-form layout="inline"> - <
|
