diff options
| author | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-05-06 19:51:14 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-05-06 19:51:14 +0300 |
| commit | f22dd6b53d736556377080a305c40be2db3c8cce (patch) | |
| tree | caae9937645094ccf2513ac46a2bfa5ca446df3b /web/html/xui | |
| parent | 735df6bd4ed18d656355067826a6f5e50495c63e (diff) | |
[feature] multi-user shadowsocks @alireza0
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
Diffstat (limited to 'web/html/xui')
| -rw-r--r-- | web/html/xui/client_modal.html | 11 | ||||
| -rw-r--r-- | web/html/xui/form/client.html | 3 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/shadowsocks.html | 83 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/trojan.html | 6 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vless.html | 6 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vmess.html | 6 | ||||
| -rw-r--r-- | web/html/xui/inbound_modal.html | 1 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 30 |
8 files changed, 131 insertions, 15 deletions
diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index bf4ed92a..e459b520 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -44,7 +44,7 @@ if (this.clients[index].expiryTime < 0){ this.delayedStart = true; } - this.oldClientId = this.dbInbound.protocol == "trojan" ? this.clients[index].password : this.clients[index].id; + this.oldClientId = this.getClientId(dbInbound.protocol,clients[index]); } else { this.addClient(this.inbound.protocol, this.clients); } @@ -56,14 +56,23 @@ case Protocols.VMESS: return clientSettings.vmesses; case Protocols.VLESS: return clientSettings.vlesses; case Protocols.TROJAN: return clientSettings.trojans; + case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; default: return null; } }, + getClientId(protocol, client) { + switch(protocol){ + case Protocols.TROJAN: return client.password; + case Protocols.SHADOWSOCKS: return client.email; + default: return client.id; + } + }, 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()); + case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks()); default: return null; } }, diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index 501861db..1740e74b 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -18,7 +18,8 @@ <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-form-item label="Password" v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS"> + <a-icon v-if="inbound.protocol === Protocols.SHADOWSOCKS" @click="client.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon> <a-input v-model.trim="client.password" style="width: 150px;" ></a-input> </a-form-item> <a-form-item label='{{ i18n "additional" }} ID' v-if="inbound.protocol === Protocols.VMESS"> diff --git a/web/html/xui/form/protocol/shadowsocks.html b/web/html/xui/form/protocol/shadowsocks.html index 718ba894..3c63fe01 100644 --- a/web/html/xui/form/protocol/shadowsocks.html +++ b/web/html/xui/form/protocol/shadowsocks.html @@ -1,5 +1,87 @@ {{define "form/shadowsocks"}} <a-form layout="inline"> + <a-collapse activeKey="0" v-for="(client, index) in inbound.settings.shadowsockses.slice(0,1)" v-if="!isEdit"> + <a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'> + <a-form-item> + <span slot="label"> + <span>{{ i18n "pages.inbounds.Email" }}</span> + <a-tooltip> + <template slot="title"> + <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + </template> + <a-icon @click="getNewEmail(client)" type="sync"></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"> + <a-icon @click="client.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon> + <a-input v-model.trim="client.password" style="width: 150px;"></a-input> + </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> + <span slot="label"> + <span>{{ i18n "pages.inbounds.IPLimit" }}</span> + <a-tooltip> + <template slot="title"> + <span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span> + </template> + <a-icon type="question-circle" theme="filled"></a-icon> + </a-tooltip> + </span> + <a-input-number v-model="client.limitIp" min="0" style="width: 70px;"></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="client._totalGB" :min="0"></a-input-number> + </a-form-item> + <a-form-item label='{{ i18n "pages.client.delayedStart" }}'> + <a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch> + </a-form-item> + <a-form-item label='{{ i18n "pages.client.expireDays" }}'> + <a-input-number v-model.number="delayedExpireDays" :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:ss' }" format="YYYY-MM-DD HH:mm:ss" + :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''" + v-model="client._expiryTime" style="width: 170px;"></a-date-picker> + </a-form-item> + </a-collapse-panel> + </a-collapse> + <a-collapse v-else> + <a-collapse-panel :header="'{{ i18n "pages.client.clientCount"}} : ' + inbound.settings.shadowsockses.length"> + <table width="100%"> + <tr class="client-table-header"> + <th v-for="col in Object.keys(inbound.settings.shadowsockses[0]).slice(0, 3)">[[ col ]]</th> + </tr> + <tr v-for="(client, index) in inbound.settings.shadowsockses" :class="index % 2 == 1 ? 'client-table-odd-row' : ''"> + <td v-for="col in Object.values(client).slice(0, 3)">[[ col ]]</td> + </tr> + </table> + </a-collapse-panel> + </a-collapse> <a-form-item label='{{ i18n "encryption" }}'> <a-select v-model="inbound.settings.method" style="width: 250px;" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <a-select-option v-for="method in SSMethods" :value="method">[[ method ]]</a-select-option> @@ -15,5 +97,4 @@ <a-select-option value="udp">UDP</a-select-option> </a-select> </a-form-item> -</a-form> {{end}}
\ No newline at end of file diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html index e63943e6..1581b07c 100644 --- a/web/html/xui/form/protocol/trojan.html +++ b/web/html/xui/form/protocol/trojan.html @@ -53,6 +53,12 @@ </span> <a-input-number v-model="client._totalGB" :min="0"></a-input-number> </a-form-item> + <a-form-item label='{{ i18n "pages.client.delayedStart" }}'> + <a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch> + </a-form-item> + <a-form-item label='{{ i18n "pages.client.expireDays" }}'> + <a-input-number v-model.number="delayedExpireDays" :min="0"></a-input-number> + </a-form-item> <a-form-item> <span slot="label"> <span >{{ i18n "pages.inbounds.expireDate" }}</span> diff --git a/web/html/xui/form/protocol/vless.html b/web/html/xui/form/protocol/vless.html index 33e0c170..023c04b9 100644 --- a/web/html/xui/form/protocol/vless.html +++ b/web/html/xui/form/protocol/vless.html @@ -59,6 +59,12 @@ </span> <a-input-number v-model="client._totalGB" :min="0"></a-input-number> </a-form-item> + <a-form-item label='{{ i18n "pages.client.delayedStart" }}'> + <a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch> + </a-form-item> + <a-form-item label='{{ i18n "pages.client.expireDays" }}'> + <a-input-number v-model.number="delayedExpireDays" :min="0"></a-input-number> + </a-form-item> <a-form-item> <span slot="label"> <span >{{ i18n "pages.inbounds.expireDate" }}</span> diff --git a/web/html/xui/form/protocol/vmess.html b/web/html/xui/form/protocol/vmess.html index 6471e20d..62b80468 100644 --- a/web/html/xui/form/protocol/vmess.html +++ b/web/html/xui/form/protocol/vmess.html @@ -50,6 +50,12 @@ </span> <a-input-number v-model="client._totalGB" :min="0"></a-input-number> </a-form-item> + <a-form-item label='{{ i18n "pages.client.delayedStart" }}'> + <a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch> + </a-form-item> + <a-form-item label='{{ i18n "pages.client.expireDays" }}'> + <a-input-number v-model.number="delayedExpireDays" :min="0"></a-input-number> + </a-form-item> <a-form-item> <span slot="label"> <span >{{ i18n "pages.inbounds.expireDate" }}</span> diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html index 966de8dd..7c338e26 100644 --- a/web/html/xui/inbound_modal.html +++ b/web/html/xui/inbound_modal.html @@ -48,6 +48,7 @@ case Protocols.VMESS: return clientSettings.vmesses; case Protocols.VLESS: return clientSettings.vlesses; case Protocols.TROJAN: return clientSettings.trojans; + case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; default: return null; } }, diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 2792eb75..5d7e041f 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -116,15 +116,11 @@ <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"> - <a-menu-item v-if="dbInbound.isSS" key="qrcode"> - <a-icon type="qrcode"></a-icon> - {{ i18n "qrCode" }} - </a-menu-item> <a-menu-item key="edit"> <a-icon type="edit"></a-icon> {{ i18n "edit" }} </a-menu-item> - <template v-if="dbInbound.isTrojan || dbInbound.isVLess || dbInbound.isVMess"> + <template v-if="dbInbound.isTrojan || dbInbound.isVLess || dbInbound.isVMess || dbInbound.isSS"> <a-menu-item key="addClient"> <a-icon type="user-add"></a-icon> {{ i18n "pages.client.add"}} @@ -168,7 +164,7 @@ </template> <template slot="protocol" slot-scope="text, dbInbound"> <a-tag style="margin:0;" color="blue">[[ dbInbound.protocol ]]</a-tag> - <template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan || dbInbound.isSS"> + <template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan"> <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> @@ -231,7 +227,7 @@ {{template "client_table"}} </a-table> <a-table - v-else-if="record.protocol === Protocols.TROJAN" + v-else-if="record.protocol === Protocols.TROJAN || record.protocol === Protocols.SHADOWSOCKS" :row-key="client => client.id" :columns="innerTrojanColumns" :data-source="getInboundClients(record)" @@ -671,7 +667,7 @@ }, delClient(dbInboundId,client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); - clientId = dbInbound.protocol == "trojan" ? client.password : client.id; + clientId = this.getClientId(dbInbound.protocol,client); this.$confirm({ title: '{{ i18n "pages.inbounds.deleteInbound"}}', content: '{{ i18n "pages.inbounds.deleteInboundContent"}}', @@ -686,9 +682,17 @@ case Protocols.VMESS: return clientSettings.vmesses; case Protocols.VLESS: return clientSettings.vlesses; case Protocols.TROJAN: return clientSettings.trojans; + case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; default: return null; } }, + getClientId(protocol, client) { + switch(protocol){ + case Protocols.TROJAN: return client.password; + case Protocols.SHADOWSOCKS: return client.email; + default: return client.id; + } + }, showQrcode(dbInbound, clientIndex) { const link = dbInbound.genLink(clientIndex); qrModal.show('{{ i18n "qrCode"}}', link, dbInbound); @@ -707,7 +711,7 @@ clients = this.getClients(dbInbound.protocol, inbound.settings); index = this.findIndexOfClient(clients, client); clients[index].enable = !clients[index].enable; - clientId = dbInbound.protocol == "trojan" ? clients[index].password : clients[index].id; + clientId = this.getClientId(dbInbound.protocol,clients[index]); await this.updateClient(clients[index],dbInboundId, clientId); this.loading(false); }, @@ -719,11 +723,13 @@ }, getInboundClients(dbInbound) { if(dbInbound.protocol == Protocols.VLESS) { - return dbInbound.toInbound().settings.vlesses + return dbInbound.toInbound().settings.vlesses; } else if(dbInbound.protocol == Protocols.VMESS) { - return dbInbound.toInbound().settings.vmesses + return dbInbound.toInbound().settings.vmesses; } else if(dbInbound.protocol == Protocols.TROJAN) { - return dbInbound.toInbound().settings.trojans + return dbInbound.toInbound().settings.trojans; + } else if(dbInbound.protocol == Protocols.SHADOWSOCKS) { + return dbInbound.toInbound().settings.shadowsockses; } }, resetClientTraffic(client,dbInboundId) { |
