diff options
Diffstat (limited to 'web/html')
| -rw-r--r-- | web/html/common/qrcode_modal.html | 24 | ||||
| -rw-r--r-- | web/html/xui/inbound_info_modal.html | 17 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 23 | ||||
| -rw-r--r-- | web/html/xui/settings.html | 96 |
4 files changed, 130 insertions, 30 deletions
diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 3bda4c29..7cc317ef 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -8,13 +8,23 @@ {{ i18n "pages.inbounds.clickOnQRcode" }} </a-tag> <template v-if="app.subSettings.enable && qrModal.subId"> - <a-divider>Subscription</a-divider> - <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas></div> + <a-divider>{{ i18n "pages.settings.subSettings"}}</a-divider> + <canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" + id="qrCode-sub" + style="width: 100%; height: 100%; display: flex; border-radius: 1rem;"> + </canvas> + <a-divider>{{ i18n "pages.settings.subSettings"}} Json</a-divider> + <canvas @click="copyToClipboard('qrCode-subJson',genSubJsonLink(qrModal.client.subId))" + id="qrCode-subJson" + style="width: 100%; height: 100%; display: flex; border-radius: 1rem;"> + </canvas> </template> <a-divider>{{ i18n "pages.inbounds.client" }}</a-divider> <template v-for="(row, index) in qrModal.qrcodes"> - <a-tag color="green" style="margin: 10px 0; display: block; text-align: center;">[[ row.remark ]]</a-tag> - <div class="qr-bg"><canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas></div> + <a-tag color="blue" style="margin: 10px 0; display: block; text-align: center;">[[ row.remark ]]</a-tag> + <canvas @click="copyToClipboard('qrCode-'+index, row.link)" + :id="'qrCode-'+index" + style="width: 100%; height: 100%; display: flex; border-radius: 1rem;"></canvas> </template> </a-modal> @@ -82,12 +92,16 @@ }, genSubLink(subID) { return app.subSettings.subURI+subID; + }, + genSubJsonLink(subID) { + return app.subSettings.subJsonURI+subID; } }, updated() { if (qrModal.client && qrModal.client.subId) { qrModal.subId = qrModal.client.subId; this.setQrCode("qrCode-sub", this.genSubLink(qrModal.subId)); + this.setQrCode("qrCode-subJson", this.genSubJsonLink(qrModal.subId)); } qrModal.qrcodes.forEach((element, index) => { this.setQrCode("qrCode-" + index, element.link); @@ -96,4 +110,4 @@ }); </script> -{{end}} +{{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 23f8bd47..c8341651 100644 --- a/web/html/xui/inbound_info_modal.html +++ b/web/html/xui/inbound_info_modal.html @@ -166,7 +166,7 @@ <template v-if="app.subSettings.enable && infoModal.clientSettings.subId"> <a-divider>Subscription URL</a-divider> <a-row> - <a-col :sx="24" :md="22"><a :href="[[ infoModal.subLink ]]" target="_blank">[[ infoModal.subLink ]]</a></a-col> + <a-col :sx="24" :md="22">SUB: <a :href="[[ infoModal.subLink ]]" target="_blank">[[ infoModal.subLink ]]</a></a-col> <a-col :sx="24" :md="2" style="text-align: right;"> <a-tooltip title='{{ i18n "copy" }}'> <button class="ant-btn ant-btn-primary" id="copy-sub-link" @click="copyToClipboard('copy-sub-link', infoModal.subLink)"> @@ -175,6 +175,16 @@ </a-tooltip> </a-col> </a-row> + <a-row> + <a-col :sx="24" :md="22">JSON: <a :href="[[ infoModal.subJsonLink ]]" target="_blank">[[ infoModal.subJsonLink ]]</a></a-col> + <a-col :sx="24" :md="2" style="text-align: right; margin-top: 5px;"> + <a-tooltip title='{{ i18n "copy" }}'> + <button class="ant-btn ant-btn-primary" id="copy-subJson-link" @click="copyToClipboard('copy-subJson-link', infoModal.subJsonLink)"> + <a-icon type="snippets"></a-icon> + </button> + </a-tooltip> + </a-col> + </a-row> </template> <template v-if="app.tgBotEnable && infoModal.clientSettings.tgId"> <a-divider>Telegram ID</a-divider> @@ -345,6 +355,7 @@ index: null, isExpired: false, subLink: '', + subJsonLink: '', show(dbInbound, index) { this.index = index; this.inbound = dbInbound.toInbound(); @@ -360,6 +371,7 @@ if (this.clientSettings) { if (this.clientSettings.subId) { this.subLink = this.genSubLink(this.clientSettings.subId); + this.subJsonLink = this.genSubJsonLink(this.clientSettings.subId); } } this.visible = true; @@ -369,6 +381,9 @@ }, genSubLink(subID) { return app.subSettings.subURI+subID; + }, + genSubJsonLink(subID) { + return app.subSettings.subJsonURI+subID; } }; diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index f1f14275..a2365cde 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -65,11 +65,6 @@ </a-alert> </transition> <transition name="list" appear> - <a-tag v-if="false" color="red" style="margin-bottom: 10px"> - Please go to the panel settings as soon as possible to modify the username and password, otherwise there may be a risk of leaking account information - </a-tag> - </transition> - <transition name="list" appear> <a-card hoverable> <a-row> <a-col :xs="24" :sm="24" :lg="12"> @@ -576,7 +571,8 @@ refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000, subSettings: { enable : false, - subURI : '' + subURI : '', + subJsonURI : '', }, remarkModel: '-ieo', datepicker: 'gregorian', @@ -623,7 +619,8 @@ this.tgBotEnable = tgBotEnable; this.subSettings = { enable : subEnable, - subURI: subURI + subURI: subURI, + subJsonURI: subJsonURI }; this.pageSize = pageSize; this.remarkModel = remarkModel; @@ -997,7 +994,7 @@ }, delInbound(dbInboundId) { this.$confirm({ - title: '{{ i18n "pages.inbounds.deleteInbound"}}', + title: '{{ i18n "pages.inbounds.deleteInbound"}}' + ' #' + dbInboundId, content: '{{ i18n "pages.inbounds.deleteInboundContent"}}', class: themeSwitcher.currentTheme, okText: '{{ i18n "delete"}}', @@ -1010,7 +1007,7 @@ clientId = this.getClientId(dbInbound.protocol, client); if (confirmation){ this.$confirm({ - title: '{{ i18n "pages.inbounds.deleteClient"}}', + title: '{{ i18n "pages.inbounds.deleteClient"}}' + ' ' + client.email, content: '{{ i18n "pages.inbounds.deleteClientContent"}}', class: themeSwitcher.currentTheme, okText: '{{ i18n "delete"}}', @@ -1301,7 +1298,7 @@ pagination(obj){ if (this.pageSize > 0 && obj.length>this.pageSize) { // Set page options based on object size - sizeOptions = [] + sizeOptions = []; for (i=this.pageSize;i<=obj.length;i=i+this.pageSize) { sizeOptions.push(i.toString()); } @@ -1314,8 +1311,8 @@ position: 'bottom', pageSize: this.pageSize, pageSizeOptions: sizeOptions - } - return p + }; + return p; } return false }, @@ -1369,7 +1366,6 @@ } }, }); - </script> {{template "inboundModal"}} @@ -1379,6 +1375,5 @@ {{template "inboundInfoModal"}} {{template "clientsModal"}} {{template "clientsBulkModal"}} - </body> </html> diff --git a/web/html/xui/settings.html b/web/html/xui/settings.html index a7c72f73..c6edc506 100644 --- a/web/html/xui/settings.html +++ b/web/html/xui/settings.html @@ -83,7 +83,17 @@ show-icon closable > </a-alert> - </transition> + <a-alert type="error" v-if="confAlerts.length>0" style="margin-bottom: 10px" + message='{{ i18n "secAlertTitle" }}' + color="red" + show-icon closable + > + <template slot="description"> + {{ i18n "secAlertConf" }} + <li v-for="a in confAlerts">- [[ a ]]</li> + </template> + </a-alert> + </transition> <a-space direction="vertical"> <a-card hoverable style="margin-bottom: .5rem; overflow-x: hidden;"> <a-row style="display: flex; flex-wrap: wrap; align-items: center;"> @@ -93,9 +103,7 @@ <a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button> </a-space> </a-col> - <a-col :xs="24" :sm="14"> - <template> - <div> + <a-col :xs="24" :sm="16"> <template> <div> <a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"> @@ -104,8 +112,6 @@ message='{{ i18n "pages.settings.infoDesc" }}' show-icon > - </div> - </template> </div> </template> </a-col> @@ -173,7 +179,6 @@ <a-col :lg="24" :xl="12"> <a-list-item-meta title="Language" /> </a-col> - <a-col :lg="24" :xl="12"> <template> <a-select @@ -243,7 +248,6 @@ <a-button type="primary" :loading="this.changeSecret" @click="updateSecret">{{ i18n "confirm" }}</a-button> </a-form> </a-tab-pane> - <a-tab-pane key="3" tab='{{ i18n "pages.settings.TGBotSettings"}}'> <a-list item-layout="horizontal"> <setting-list-item type="switch" title='{{ i18n "pages.settings.telegramBotEnable" }}' desc='{{ i18n "pages.settings.telegramBotEnableDesc" }}' v-model="allSetting.tgBotEnable"></setting-list-item> @@ -266,8 +270,7 @@ ref="selectBotLang" v-model="allSetting.tgLang" :dropdown-class-name="themeSwitcher.currentTheme" - style="width: 100%" - > + style="width: 100%"> <a-select-option :value="l.value" :label="l.value" v-for="l in supportLangs"> <span role="img" :aria-label="l.name" v-text="l.icon"></span> <span v-text="l.name"></span> @@ -294,6 +297,17 @@ <setting-list-item type="number" title='{{ i18n "pages.settings.subUpdates"}}' desc='{{ i18n "pages.settings.subUpdatesDesc"}}' v-model="allSetting.subUpdates"></setting-list-item> </a-list> </a-tab-pane> + <a-tab-pane key="5" tab='{{ i18n "pages.settings.subSettings" }} Json' v-if="allSetting.subEnable"> + <a-list item-layout="horizontal"> + <setting-list-item type="text" title='{{ i18n "pages.settings.subPath"}}' desc='{{ i18n "pages.settings.subPathDesc"}}' v-model="allSetting.subJsonPath"></setting-list-item> + <setting-list-item type="text" title='{{ i18n "pages.settings.subURI"}}' desc='{{ i18n "pages.settings.subURIDesc"}}' v-model="allSetting.subJsonURI" placeholder="(http|https)://domain[:port]/path/"></setting-list-item> + <setting-list-item type="switch" title='{{ i18n "pages.settings.fragment"}}' desc='{{ i18n "pages.settings.fragmentDesc"}}' v-model="fragment"></setting-list-item> + <template v-if="fragment"> + <setting-list-item type="text" title='length' v-model="fragmentLength" placeholder="100-200"></setting-list-item> + <setting-list-item type="text" title='Interval' v-model="fragmentInterval" placeholder="10-20"></setting-list-item> + </template> + </a-list> + </a-tab-pane> </a-tabs> </a-space> </a-spin> @@ -324,6 +338,24 @@ remarkSeparators: [' ','-','_','@',':','~','|',',','.','/'], datepickerList: [{name:'Gregorian (Standard)', value: 'gregorian'}, {name:'Jalalian (شمسی)', value: 'jalalian'}], remarkSample: '', + defaultFragment: { + tag: "fragment", + protocol: "freedom", + settings: { + domainStrategy: "AsIs", + fragment: { + packets: "tlshello", + length: "100-200", + interval: "10-20" + } + }, + streamSettings: { + sockopt: { + tcpKeepAliveIdle: 100, + TcpNoDelay: true + } + } + }, get remarkModel() { rm = this.allSetting.remarkModel; return rm.length>1 ? rm.substring(1).split('') : []; @@ -452,6 +484,50 @@ } }, }, + computed: { + fragment: { + get: function() { return this.allSetting?.subJsonFragment != ""; }, + set: function (v) { + this.allSetting.subJsonFragment = v ? JSON.stringify(this.defaultFragment) : ""; + } + }, + fragmentLength: { + get: function() { return this.fragment ? JSON.parse(this.allSetting.subJsonFragment).settings.fragment.length : ""; }, + set: function(v) { + if (v != ""){ + newFragment = JSON.parse(this.allSetting.subJsonFragment); + newFragment.settings.fragment.length = v; + this.allSetting.subJsonFragment = JSON.stringify(newFragment); + } + } + }, + fragmentInterval: { + get: function() { return this.fragment ? JSON.parse(this.allSetting.subJsonFragment).settings.fragment.interval : ""; }, + set: function(v) { + if (v != ""){ + newFragment = JSON.parse(this.allSetting.subJsonFragment); + newFragment.settings.fragment.interval = v; + this.allSetting.subJsonFragment = JSON.stringify(newFragment); + } + } + }, + confAlerts: { + get: function() { + if (!this.allSetting) return []; + var alerts = [] + if (this.allSetting.port == 54321) alerts.push('{{ i18n "pages.settings.panelPort"}}'); + panelPath = window.location.pathname.split('/').length<4 + if (panelPath && this.allSetting.webBasePath == '/') alerts.push('{{ i18n "pages.settings.panelSettings"}} {{ i18n "pages.settings.panelUrlPath"}}'); + if (this.allSetting.subEnable) { + subPath = this.allSetting.subURI.length >0 ? new URL(this.allSetting.subURI).pathname : this.allSetting.subPath; + if (subPath == '/sub/') alerts.push('{{ i18n "pages.settings.subSettings"}} {{ i18n "pages.settings.subPath"}}'); + subJsonPath = this.allSetting.subJsonURI.length >0 ? new URL(this.allSetting.subJsonURI).pathname : this.allSetting.subJsonPath; + if (subJsonPath == '/json/') alerts.push('JSON {{ i18n "pages.settings.subPath"}}'); + } + return alerts + } + } + }, async mounted() { if (window.location.protocol !== "https:") { this.showAlert = true; |
