diff options
| author | Ho3ein <ho3ein.sanaei@gmail.com> | 2023-05-13 12:48:36 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-13 12:48:36 +0300 |
| commit | 5468069befd602a7ae51deb5b76150ee16d426d6 (patch) | |
| tree | a41b4492b37e52e033b2f4e027da05ce8893ae50 | |
| parent | 3bec9ee2737d0a8c49f4d705f1d8c8925bb8a2a8 (diff) | |
| parent | 0cce35784eb2ab8ce42e88bdf63e0284254d2e14 (diff) | |
Merge pull request #420 from hamid-gh98/main
[fix] russia domains in settings and More....
27 files changed, 225 insertions, 88 deletions
@@ -1,4 +1,5 @@ -# 3x-ui +# 3x-ui + > **Disclaimer: This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment** [](https://github.com/MHSanaei/3x-ui/releases) @@ -12,7 +13,8 @@ **If you think this project is helpful to you, you may wish to give a** :star2: **Buy Me a Coffee :** - - Tron USDT (TRC20): `TXncxkvhkDWGts487Pjqq1qT9JmwRUz8CC` + +- Tron USDT (TRC20): `TXncxkvhkDWGts487Pjqq1qT9JmwRUz8CC` # Install & Upgrade @@ -47,12 +49,12 @@ or you can use x-ui menu then number '16' (Apply for an SSL Certificate) Before you set ssl on settings -- http://ip:2053/xui -- http://domain:2053/xui +- http://ip:2053/panel +- http://domain:2053/panel After you set ssl on settings -- https://yourdomain:2053/xui +- https://yourdomain:2053/panel # Environment Variables @@ -69,6 +71,31 @@ Example: XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go ``` +# Install with Docker + +1. Install Docker: + ```sh + bash <(curl -sSL https://get.docker.com) + ``` +2. Run 3x-ui: + + ```sh + docker compose up -d + ``` + + OR + + ```sh + docker run -itd \ + -e XRAY_VMESS_AEAD_FORCED=false \ + -v $PWD/db/:/etc/x-ui/ \ + -v $PWD/cert/:/root/cert/ \ + --network=host \ + --restart=unless-stopped \ + --name 3x-ui \ + ghcr.io/mhsanaei/3x-ui:latest + ``` + # Xray Configurations: **copy and paste to xray Configuration :** (you don't need to do this if you have a fresh install) @@ -173,19 +200,19 @@ Reference syntax: | `POST` | `"/clientIps/:email"` | Client Ip address | | `POST` | `"/clearClientIps/:email"` | Clear Client Ip address | | `POST` | `"/addClient"` | Add Client to inbound | -| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId* | -| `POST` | `"/updateClient/:clientId"` | Update Client by clientId* | +| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* | +| `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* | | `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic | | `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds | | `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound | | `POST` | `"/delDepletedClients/:id"` | Delete inbound depleted clients (-1: all) | -*- The field `clientId` should be filled by: +\*- The field `clientId` should be filled by: + - `client.id` for VMESS and VLESS - `client.password` for TROJAN - `client.email` for Shadowsocks - - [Postman Collection](https://gist.github.com/mehdikhody/9a862801a2e41f6b5fb6bbc7e1326044) # A Special Thanks To diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..f0231309 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +--- +version: "3.9" + +services: + 3x-ui: + image: ghcr.io/mhsanaei/3x-ui:latest + container_name: 3x-ui + volumes: + - $PWD/db/:/etc/x-ui/ + - $PWD/cert/:/root/cert/ + environment: + XRAY_VMESS_AEAD_FORCED: "false" + tty: true + network_mode: host + restart: unless-stopped diff --git a/web/controller/index.go b/web/controller/index.go index 802f3f7d..b0ee83f8 100644 --- a/web/controller/index.go +++ b/web/controller/index.go @@ -39,7 +39,7 @@ func (a *IndexController) initRouter(g *gin.RouterGroup) { func (a *IndexController) index(c *gin.Context) { if session.IsLogin(c) { - c.Redirect(http.StatusTemporaryRedirect, "xui/") + c.Redirect(http.StatusTemporaryRedirect, "panel/") return } html(c, "login.html", "pages.login.title", nil) @@ -101,5 +101,4 @@ func (a *IndexController) getSecretStatus(c *gin.Context) { if err == nil { jsonObj(c, status, nil) } - } diff --git a/web/controller/setting.go b/web/controller/setting.go index bd9c2a5f..248f3ee5 100644 --- a/web/controller/setting.go +++ b/web/controller/setting.go @@ -3,6 +3,7 @@ package controller import ( "errors" "time" + "x-ui/util/common" "x-ui/web/entity" "x-ui/web/service" "x-ui/web/session" @@ -44,6 +45,7 @@ func (a *SettingController) initRouter(g *gin.RouterGroup) { g.GET("/getDefaultJsonConfig", a.getDefaultJsonConfig) g.POST("/updateUserSecret", a.updateSecret) g.POST("/getUserSecret", a.getUserSecret) + g.GET("/searchDatafiles", a.searchDatafiles) } func (a *SettingController) getAllSetting(c *gin.Context) { @@ -149,6 +151,7 @@ func (a *SettingController) updateSecret(c *gin.Context) { } jsonMsg(c, I18n(c, "pages.settings.toasts.modifyUser"), err) } + func (a *SettingController) getUserSecret(c *gin.Context) { loginUser := session.GetLoginUser(c) user := a.userService.GetUserSecret(loginUser.Id) @@ -156,3 +159,18 @@ func (a *SettingController) getUserSecret(c *gin.Context) { jsonObj(c, user, nil) } } + +func (a *SettingController) searchDatafiles(c *gin.Context) { + searchString := c.Query("query") + if searchString == "" { + err := common.NewError("data query parameter is empty") + jsonMsg(c, "Invalid query:", err) + return + } + found, err := a.settingService.SearchDatafiles(searchString) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + jsonObj(c, found, nil) +} diff --git a/web/controller/xui.go b/web/controller/xui.go index 1844181d..700bd52c 100644 --- a/web/controller/xui.go +++ b/web/controller/xui.go @@ -18,7 +18,7 @@ func NewXUIController(g *gin.RouterGroup) *XUIController { } func (a *XUIController) initRouter(g *gin.RouterGroup) { - g = g.Group("/xui") + g = g.Group("/panel") g.Use(a.checkLogin) g.GET("/", a.index) diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 2bd2f00f..855c349a 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -7,7 +7,10 @@ <a-tag color="green" style="margin-bottom: 10px;display: block;text-align: center;"> {{ i18n "pages.inbounds.clickOnQRcode" }} </a-tag> - <canvas @click="copyToClipboard()" id="qrCode" style="width: 100%; height: 100%;"></canvas> + <a-tag v-if="qrModal.clientName" color="orange" style="margin-bottom: 10px;display: block;text-align: center;"> + {{ i18n "pages.inbounds.email" }}: "[[ qrModal.clientName ]]" + </a-tag> + <canvas @click="copyToClipboard()" id="qrCode" style="width: 100%; height: 100%; margin-top: 10px;"></canvas> </a-modal> <script> @@ -18,14 +21,16 @@ inbound: new Inbound(), dbInbound: new DBInbound(), copyText: '', + clientName: null, qrcode: null, clipboard: null, visible: false, - show: function (title = '', content = '', dbInbound = new DBInbound(), copyText = '') { + show: function (title = '', content = '', dbInbound = new DBInbound(), copyText = '', clientName = null) { this.title = title; this.content = content; this.dbInbound = dbInbound; this.inbound = dbInbound.toInbound(); + this.clientName = clientName; if (ObjectUtil.isEmpty(copyText)) { this.copyText = content; } else { @@ -50,6 +55,7 @@ }; const qrModalApp = new Vue({ + delimiters: ['[[', ']]'], el: '#qrcode-modal', data: { qrModal: qrModal, diff --git a/web/html/login.html b/web/html/login.html index 1b6478de..a2bde74f 100644 --- a/web/html/login.html +++ b/web/html/login.html @@ -46,7 +46,7 @@ </style> <body> -<a-layout id="app" v-cloak :class="themeSwitcher.darkClass"> +<a-layout id="app" v-cloak :class="themeSwitcher.darkCardClass"> <transition name="list" appear> <a-layout-content> <a-row type="flex" justify="center"> @@ -120,10 +120,10 @@ secretEnable: false, lang: "" }, - created() { + async created() { this.updateBackground(); this.lang = getLang(); - this.secretEnable = this.getSecretStatus(); + this.secretEnable = await this.getSecretStatus(); }, methods: { async login() { @@ -131,7 +131,7 @@ const msg = await HttpUtil.post('/login', this.user); this.loading = false; if (msg.success) { - location.href = basePath + 'xui/'; + location.href = basePath + 'panel/'; } }, async getSecretStatus() { diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index 89175f31..f7faf888 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -135,7 +135,7 @@ client.email = string; }, async getDBClientIps(email, event) { - const msg = await HttpUtil.post('/xui/inbound/clientIps/' + email); + const msg = await HttpUtil.post('/panel/inbound/clientIps/' + email); if (!msg.success) { return; } @@ -149,7 +149,7 @@ } }, async clearDBClientIps(email) { - const msg = await HttpUtil.post('/xui/inbound/clearClientIps/' + email); + const msg = await HttpUtil.post('/panel/inbound/clearClientIps/' + email); if (!msg.success) { return; } @@ -164,7 +164,7 @@ cancelText: '{{ i18n "cancel"}}', onOk: async () => { iconElement.disabled = true; - const msg = await HttpUtil.postWithModal('/xui/inbound/' + dbInboundId + '/resetClientTraffic/' + email); + const msg = await HttpUtil.postWithModal('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + email); if (msg.success) { this.clientModal.clientStats.up = 0; this.clientModal.clientStats.down = 0; diff --git a/web/html/xui/common_sider.html b/web/html/xui/common_sider.html index 94a2e4a3..58072f82 100644 --- a/web/html/xui/common_sider.html +++ b/web/html/xui/common_sider.html @@ -1,17 +1,17 @@ {{define "menuItems"}} -<a-menu-item key="{{ .base_path }}xui/"> +<a-menu-item key="{{ .base_path }}panel/"> <a-icon type="dashboard"></a-icon> <span>{{ i18n "menu.dashboard"}}</span> </a-menu-item> -<a-menu-item key="{{ .base_path }}xui/inbounds"> +<a-menu-item key="{{ .base_path }}panel/inbounds"> <a-icon type="user"></a-icon> <span>{{ i18n "menu.inbounds"}}</span> </a-menu-item> -<a-menu-item key="{{ .base_path }}xui/settings"> +<a-menu-item key="{{ .base_path }}panel/settings"> <a-icon type="setting"></a-icon> <span>{{ i18n "menu.settings"}}</span> </a-menu-item> -<!--<a-menu-item key="{{ .base_path }}xui/clients">--> +<!--<a-menu-item key="{{ .base_path }}panel/clients">--> <!-- <a-icon type="laptop"></a-icon>--> <!-- <span>Client</span>--> <!--</a-menu-item>--> diff --git a/web/html/xui/component/themeSwitch.html b/web/html/xui/component/themeSwitch.html index 35013a9e..7cbedecf 100644 --- a/web/html/xui/component/themeSwitch.html +++ b/web/html/xui/component/themeSwitch.html @@ -28,7 +28,7 @@ isDarkTheme, bgStyle: `background: ${colors[theme].bg};`, textStyle: `color: ${colors[theme].text};`, - darkClass: isDarkTheme ? 'ant-card-dark' : '', + darkClass: isDarkTheme ? 'ant-dark' : '', darkCardClass: isDarkTheme ? 'ant-card-dark' : '', darkDrawerClass: isDarkTheme ? 'ant-drawer-dark' : '', get currentTheme() { @@ -40,7 +40,7 @@ localStorage.setItem('dark-mode', this.isDarkTheme); this.bgStyle = `background: ${colors[this.theme].bg};`; this.textStyle = `color: ${colors[this.theme].text};`; - this.darkClass = this.isDarkTheme ? 'ant-card-dark' : ''; + this.darkClass = this.isDarkTheme ? 'ant-dark' : ''; this.darkCardClass = this.isDarkTheme ? 'ant-card-dark' : ''; this.darkDrawerClass = this.isDarkTheme ? 'ant-drawer-dark' : ''; }, diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index c8ab09cf..1aaf9073 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -11,10 +11,10 @@ <br> <a-form-item> <span slot="label"> - <span>{{ i18n "pages.inbounds.Email" }}</span> + <span>{{ i18n "pages.inbounds.email" }}</span> <a-tooltip> <template slot="title"> - <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> <a-icon type="sync" @click="getNewEmail(client)"></a-icon> </a-tooltip> diff --git a/web/html/xui/form/protocol/shadowsocks.html b/web/html/xui/form/protocol/shadowsocks.html index f37c1a90..b59b4722 100644 --- a/web/html/xui/form/protocol/shadowsocks.html +++ b/web/html/xui/form/protocol/shadowsocks.html @@ -4,10 +4,10 @@ <a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'> <a-form-item> <span slot="label"> - <span>{{ i18n "pages.inbounds.Email" }}</span> + <span>{{ i18n "pages.inbounds.email" }}</span> <a-tooltip> <template slot="title"> - <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> <a-icon @click="getNewEmail(client)" type="sync"></a-icon> </a-tooltip> diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html index 4a2518a7..2b6a2a3b 100644 --- a/web/html/xui/form/protocol/trojan.html +++ b/web/html/xui/form/protocol/trojan.html @@ -4,10 +4,10 @@ <a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'> <a-form-item> <span slot="label"> - <span>{{ i18n "pages.inbounds.Email" }}</span> + <span>{{ i18n "pages.inbounds.email" }}</span> <a-tooltip> <template slot="title"> - <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> <a-icon type="sync" @click="getNewEmail(client)"></a-icon> </a-tooltip> diff --git a/web/html/xui/form/protocol/vless.html b/web/html/xui/form/protocol/vless.html index 12b15711..b253a4a3 100644 --- a/web/html/xui/form/protocol/vless.html +++ b/web/html/xui/form/protocol/vless.html @@ -4,10 +4,10 @@ <a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'> <a-form-item> <span slot="label"> - <span>{{ i18n "pages.inbounds.Email" }}</span> + <span>{{ i18n "pages.inbounds.email" }}</span> <a-tooltip> <template slot="title"> - <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> <a-icon type="sync" @click="getNewEmail(client)"></a-icon> </a-tooltip> diff --git a/web/html/xui/form/protocol/vmess.html b/web/html/xui/form/protocol/vmess.html index 2b02bd14..f703210b 100644 --- a/web/html/xui/form/protocol/vmess.html +++ b/web/html/xui/form/protocol/vmess.html @@ -4,10 +4,10 @@ <a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'> <a-form-item> <span slot="label"> - <span>{{ i18n "pages.inbounds.Email" }}</span> + <span>{{ i18n "pages.inbounds.email" }}</span> <a-tooltip> <template slot="title"> - <span>{{ i18n "pages.inbounds.EmailDesc" }}</span> + <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> <a-icon type="sync" @click="getNewEmail(client)"></a-icon> </a-tooltip> diff --git a/web/html/xui/inbound_info_modal.html b/web/html/xui/inbound_info_modal.html index cfaddf3b..d9d0637c 100644 --- a/web/html/xui/inbound_info_modal.html +++ b/web/html/xui/inbound_info_modal.html @@ -114,6 +114,7 @@ <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> + <td><a-icon id="copy-sub-link" type="snippets" @click="copyToClipboard('copy-sub-link', subBase + infoModal.clientSettings.subId)"></a-icon></td> </tr> <tr v-if="infoModal.clientSettings.tgId"> <td>Telegram ID</td> @@ -190,7 +191,7 @@ <div v-if="dbInbound.hasLink()"> <a-divider>URL</a-divider> <p>[[ infoModal.link ]]</p> - <button class="ant-btn ant-btn-primary" id="copy-url-link"><a-icon type="snippets"></a-icon>{{ i18n "copy" }}</button> + <button class="ant-btn ant-btn-primary" id="copy-url-link" @click="copyToClipboard('copy-url-link', infoModal.link)"><a-icon type="snippets"></a-icon>{{ i18n "copy" }}</button> </div> </a-modal> <script> @@ -218,14 +219,6 @@ this.isExpired = this.inbound.isExpiry(index); this.clientStats = this.settings.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : []; this.visible = true; - infoModalApp.$nextTick(() => { - if (this.clipboard === null) { - this.clipboard = new ClipboardJS('#copy-url-link', { - text: () => this.link, - }); - this.clipboard.on('success', () => app.$message.success('{{ i18n "copied" }}')); - } - }); }, close() { infoModal.visible = false; @@ -263,7 +256,7 @@ }, }, methods: { - copyTextToClipboard(elmentId, content) { + copyToClipboard(elmentId, content) { this.infoModal.clipboard = new ClipboardJS('#' + elmentId, { text: () => content, }); diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 080a08cc..a80fe79a 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -338,7 +338,7 @@ }, async getDBInbounds() { this.refreshing = true; - const msg = await HttpUtil.post('/xui/inbound/list'); + const msg = await HttpUtil.post('/panel/inbound/list'); if (!msg.success) { return; } @@ -346,7 +346,7 @@ this.refreshing = false; }, async getDefaultSettings() { - const msg = await HttpUtil.post('/xui/setting/defaultSettings'); + const msg = await HttpUtil.post('/panel/setting/defaultSettings'); if (!msg.success) { return; } @@ -509,7 +509,7 @@ streamSettings: baseInbound.stream.toString(), sniffing: baseInbound.canSniffing() ? baseInbound.sniffing.toString() : '{}', }; - await this.submit('/xui/inbound/add', data, inModal); + await this.submit('/panel/inbound/add', data, inModal); }, openAddInbound() { inModal.show({ @@ -558,7 +558,7 @@ if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString(); if (inbound.canSniffing()) data.sniffing = inbound.sniffing.toString(); - await this.submit('/xui/inbound/add', data, inModal); + await this.submit('/panel/inbound/add', data, inModal); }, async updateInbound(inbound, dbInbound) { const data = { @@ -577,7 +577,7 @@ if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString(); if (inbound.canSniffing()) data.sniffing = inbound.sniffing.toString(); - await this.submit(`/xui/inbound/update/${dbInbound.id}`, data, inModal); + await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); }, openAddClient(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -632,14 +632,14 @@ id: dbInboundId, settings: '{"clients": [' + clients.toString() + ']}', }; - await this.submit(`/xui/inbound/addClient`, data); + await this.submit(`/panel/inbound/addClient`, data); }, async updateClient(client, dbInboundId, clientId) { const data = { id: dbInboundId, settings: '{"clients": [' + client.toString() + ']}', }; - await this.submit(`/xui/inbound/updateClient/${clientId}`, data); + await this.submit(`/panel/inbound/updateClient/${clientId}`, data); }, resetTraffic(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -664,7 +664,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "delete"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/del/' + dbInboundId), + onOk: () => this.submit('/panel/inbound/del/' + dbInboundId), }); }, delClient(dbInboundId, client) { @@ -676,7 +676,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "delete"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit(`/xui/inbound/${dbInboundId}/delClient/${clientId}`), + onOk: () => this.submit(`/panel/inbound/${dbInboundId}/delClient/${clientId}`), }); }, getClients(protocol, clientSettings) { @@ -696,15 +696,16 @@ } }, showQrcode(dbInbound, clientIndex) { + const clientName = JSON.parse(dbInbound.settings).clients[clientIndex].email; const link = dbInbound.genLink(clientIndex); - qrModal.show('{{ i18n "qrCode"}}', link, dbInbound); + qrModal.show('{{ i18n "qrCode"}}', link, dbInbound, '', clientName); }, showInfo(dbInbound, index) { infoModal.show(dbInbound, index); }, switchEnable(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); - this.submit(`/xui/inbound/update/${dbInboundId}`, dbInbound); + this.submit(`/panel/inbound/update/${dbInboundId}`, dbInbound); }, async switchEnableClient(dbInboundId, client) { this.loading() @@ -741,7 +742,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "reset"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email), + onOk: () => this.submit('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email), }) }, resetAllTraffic() { @@ -751,7 +752,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "reset"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/resetAllTraffics'), + onOk: () => this.submit('/panel/inbound/resetAllTraffics'), }); }, resetAllClientTraffics(dbInboundId) { @@ -761,7 +762,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "reset"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId), + onOk: () => this.submit('/panel/inbound/resetAllClientTraffics/' + dbInboundId), }) }, delDepletedClients(dbInboundId) { @@ -771,7 +772,7 @@ class: themeSwitcher.darkCardClass, okText: '{{ i18n "reset"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/delDepletedClients/' + dbInboundId), + onOk: () => this.submit('/panel/inbound/delDepletedClients/' + dbInboundId), }) }, isExpiry(dbInbound, index) { diff --git a/web/html/xui/index.html b/web/html/xui/index.html index 73936b29..fa7d576e 100644 --- a/web/html/xui/index.html +++ b/web/html/xui/index.html @@ -500,7 +500,7 @@ return; } this.loading(true); - const restartMsg = await HttpUtil.post("/xui/setting/restartPanel"); + const restartMsg = await HttpUtil.post("/panel/setting/restartPanel"); this.loading(false); if (restartMsg.success) { this.loading(true); diff --git a/web/html/xui/settings.html b/web/html/xui/settings.html index d50822c2..9dec0e0c 100644 --- a/web/html/xui/settings.html +++ b/web/html/xui/settings.html @@ -153,6 +153,7 @@ <setting-list-item type="switch" title='{{ i18n "pages.settings.templates.xrayConfigPrivateIp"}}' desc='{{ i18n "pages.settings.templates.xrayConfigPrivateIpDesc"}}' v-model="privateIpSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.settings.templates.xrayConfigAds"}}' desc='{{ i18n "pages.settings.templates.xrayConfigAdsDesc"}}' v-model="AdsSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.settings.templates.xrayConfigPorn"}}' desc='{{ i18n "pages.settings.templates.xrayConfigPornDesc"}}' v-model="PornSettings"></setting-list-item> + <setting-list-item type="switch" title='{{ i18n "pages.settings.templates.xrayConfigSpeedtest"}}' desc='{{ i18n "pages.settings.templates.xrayConfigSpeedtestDesc"}}' v-model="SpeedTestSettings"></setting-list-item> </a-collapse-panel> <a-collapse-panel header='{{ i18n "pages.settings.templates.countryConfigs"}}'> <a-row :xs="24" :sm="24" :lg="12"> @@ -285,6 +286,7 @@ "geosite:spotify-ads" ], porn: ["geosite:category-porn"], + speedtest:
|
