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:
authorMHSanaei <mc.sanaei@gmail.com>2023-02-09 22:18:06 +0300
committerMHSanaei <mc.sanaei@gmail.com>2023-02-09 22:18:06 +0300
commitb73e4173a3c1e69e02ad6b4e3b43e425e57a5be9 (patch)
treed95d2f5e903d97082e11eb9f9023c165b1bde388 /web/html/common
3x-ui
Diffstat (limited to 'web/html/common')
-rw-r--r--web/html/common/head.html17
-rw-r--r--web/html/common/js.html22
-rw-r--r--web/html/common/prompt_modal.html67
-rw-r--r--web/html/common/qrcode_modal.html120
-rw-r--r--web/html/common/text_modal.html58
5 files changed, 284 insertions, 0 deletions
diff --git a/web/html/common/head.html b/web/html/common/head.html
new file mode 100644
index 00000000..f34ce62f
--- /dev/null
+++ b/web/html/common/head.html
@@ -0,0 +1,17 @@
+{{define "head"}}
+<head>
+ <meta charset="UTF-8">
+ <meta name="renderer" content="webkit">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue@1.7.2/antd.min.css">
+ <link rel="stylesheet" href="{{ .base_path }}assets/element-ui@2.15.0/theme-chalk/display.css">
+ <link rel="stylesheet" href="{{ .base_path }}assets/css/custom.css?{{ .cur_ver }}">
+ <style>
+ [v-cloak] {
+ display: none;
+ }
+ </style>
+ <title>{{ i18n .title}}</title>
+</head>
+{{end}} \ No newline at end of file
diff --git a/web/html/common/js.html b/web/html/common/js.html
new file mode 100644
index 00000000..d400196b
--- /dev/null
+++ b/web/html/common/js.html
@@ -0,0 +1,22 @@
+{{define "js"}}
+<script src="{{ .base_path }}assets/vue@2.6.12/vue.min.js"></script>
+<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
+<script src="{{ .base_path }}assets/ant-design-vue@1.7.2/antd.min.js"></script>
+<script src="{{ .base_path }}assets/base64/base64.min.js"></script>
+<script src="{{ .base_path }}assets/axios/axios.min.js"></script>
+<script src="{{ .base_path }}assets/qs/qs.min.js"></script>
+<script src="{{ .base_path }}assets/qrcode/qrious.min.js"></script>
+<script src="{{ .base_path }}assets/clipboard/clipboard.min.js"></script>
+<script src="{{ .base_path }}assets/uri/URI.min.js"></script>
+<script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/util/common.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/util/utils.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/model/xray.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/model/models.js?{{ .cur_ver }}"></script>
+<script src="{{ .base_path }}assets/js/langs.js"></script>
+<script>
+ const basePath = '{{ .base_path }}';
+ axios.defaults.baseURL = basePath;
+</script>
+{{end}} \ No newline at end of file
diff --git a/web/html/common/prompt_modal.html b/web/html/common/prompt_modal.html
new file mode 100644
index 00000000..91c26615
--- /dev/null
+++ b/web/html/common/prompt_modal.html
@@ -0,0 +1,67 @@
+{{define "promptModal"}}
+<a-modal id="prompt-modal" v-model="promptModal.visible" :title="promptModal.title"
+ :closable="true" @ok="promptModal.ok" :mask-closable="false"
+ :ok-text="promptModal.okText" cancel-text='{{ i18n "cancel" }}'>
+ <a-input id="prompt-modal-input" :type="promptModal.type"
+ v-model="promptModal.value"
+ :autosize="{minRows: 10, maxRows: 20}"
+ @keydown.enter.native="promptModal.keyEnter"
+ @keydown.ctrl.83="promptModal.ctrlS"></a-input>
+</a-modal>
+
+<script>
+
+ const promptModal = {
+ title: '',
+ type: '',
+ value: '',
+ okText: '{{ i18n "sure"}}',
+ visible: false,
+ keyEnter(e) {
+ if (this.type !== 'textarea') {
+ e.preventDefault();
+ this.ok();
+ }
+ },
+ ctrlS(e) {
+ if (this.type === 'textarea') {
+ e.preventDefault();
+ promptModal.confirm(promptModal.value);
+ }
+ },
+ ok() {
+ promptModal.close();
+ promptModal.confirm(promptModal.value);
+ },
+ confirm() {},
+ open({
+ title='',
+ type='text',
+ value='',
+ okText='{{ i18n "sure"}}',
+ confirm=() => {},
+ }) {
+ this.title = title;
+ this.type = type;
+ this.value = value;
+ this.okText = okText;
+ this.confirm = confirm;
+ this.visible = true;
+ promptModalApp.$nextTick(() => {
+ document.querySelector('#prompt-modal-input').focus();
+ });
+ },
+ close() {
+ this.visible = false;
+ }
+ };
+
+ const promptModalApp = new Vue({
+ el: '#prompt-modal',
+ data: {
+ promptModal: promptModal,
+ },
+ });
+
+</script>
+{{end}} \ No newline at end of file
diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html
new file mode 100644
index 00000000..c80f8a0e
--- /dev/null
+++ b/web/html/common/qrcode_modal.html
@@ -0,0 +1,120 @@
+{{define "qrcodeModal"}}
+<a-modal id="qrcode-modal" v-model="qrModal.visible" :title="qrModal.title"
+ :closable="true" width="300px" :ok-text="qrModal.okText"
+ cancel-text='{{ i18n "close" }}' :ok-button-props="{attrs:{id:'qr-modal-ok-btn'}}">
+ <a-tag color="green" style="margin-bottom: 10px;display: block;text-align: center;" >click on QR Code to Copy</a-tag>
+ <canvas v-if="qrModal.inbound.protocol != Protocols.VMESS && qrModal.inbound.protocol != Protocols.VLESS" id="qrCode" style="width: 100%; height: 100%;"></canvas>
+
+ <template v-if="qrModal.inbound.protocol === Protocols.VMESS" v-for="(vmess, index) in qrModal.inbound.settings.vmesses">
+ <a-tag color="red" style="margin-bottom: 10px;display: block;text-align: center;" v-text="vmess.email"></a-tag>
+ <canvas @click="copyTextToClipboard(`qrCode-vmess-${vmess.id}`,index)" :id="`qrCode-vmess-${vmess.id}`" style="width: 100%; height: 100%;"></canvas>
+ <a-divider style="height: 2px; background-color: #7e7e7e" />
+ </template>
+
+ <template v-if="qrModal.inbound.protocol === Protocols.VLESS" v-for="(vless, index) in qrModal.inbound.settings.vlesses">
+ <a-tag color="red" style="margin-bottom: 10px;display: block;text-align: center;" v-text="vless.email"></a-tag>
+ <canvas @click="copyTextToClipboard(`qrCode-vless-${vless.id}`,index)" :id="`qrCode-vless-${vless.id}`" style="width: 100%; height: 100%;"></canvas>
+ <a-divider style="height: 2px; background-color: #7e7e7e" />
+ </template>
+</a-modal>
+
+<script>
+
+ const qrModal = {
+ title: '',
+ content: '',
+ inbound: new Inbound(),
+ dbInbound: new DBInbound(),
+ okText: '',
+ copyText: '',
+ qrcode: null,
+ clipboard: null,
+ visible: false,
+ show: function (title='', content='', dbInbound=new DBInbound(),okText='{{ i18n "copy" }}', copyText='') {
+ this.title = title;
+ this.content = content;
+ this.dbInbound = dbInbound;
+ this.inbound = dbInbound.toInbound();
+ this.okText = okText;
+ if (ObjectUtil.isEmpty(copyText)) {
+ this.copyText = content;
+ } else {
+ this.copyText = copyText;
+ }
+ this.visible = true;
+ qrModalApp.$nextTick(() => {
+ if (this.clipboard === null) {
+ this.clipboard = new ClipboardJS('#qr-modal-ok-btn', {
+ text: () => this.copyText,
+ });
+ this.clipboard.on('success', () => app.$message.success('{{ i18n "copied" }}'));
+ }
+ if (this.qrcode === null) {
+ this.qrcode = new QRious({
+ element: document.querySelector('#qrCode'),
+ size: 260,
+ value: content,
+ });
+ } else {
+ this.qrcode.value = content;
+ }
+ });
+ },
+ close: function () {
+ this.visible = false;
+ },
+ };
+
+ const qrModalApp = new Vue({
+ el: '#qrcode-modal',
+ data: {
+ qrModal: qrModal,
+ },
+ methods: {
+ setQrCode(elmentId,index) {
+ content = qrModal.inbound.genLink(qrModal.dbInbound.address,qrModal.dbInbound.remark,index)
+
+ new QRious({
+ element: document.querySelector('#'+elmentId),
+ size: 260,
+ value: content,
+ });
+ },
+ copyTextToClipboard(elmentId,index) {
+ link = qrModal.inbound.genLink(qrModal.dbInbound.address,qrModal.dbInbound.remark,index)
+ this.qrModal.copyText = link
+
+ this.qrModal.clipboard = new ClipboardJS('#' + elmentId, {
+ text: () => link,
+ });
+ this.qrModal.clipboard.on('success', () => {
+ app.$message.success('{{ i18n "copied" }}')
+ this.qrModal.clipboard.destroy();
+ });
+
+
+ }
+ },
+ updated() {
+ switch (qrModal.inbound.protocol) {
+ case Protocols.VMESS:
+ vmesses = qrModal.inbound.settings.vmesses
+ for (const index in vmesses) {
+ this.setQrCode("qrCode-vmess-" + vmesses[index].id ,index)
+ }
+ break;
+ case Protocols.VLESS:
+ vlesses = qrModal.inbound.settings.vlesses
+
+ for (const index in vlesses) {
+ this.setQrCode("qrCode-vless-" + vlesses[index].id ,index)
+ }
+ break;
+ default: return null;
+ }
+
+ }
+ });
+
+</script>
+{{end}} \ No newline at end of file
diff --git a/web/html/common/text_modal.html b/web/html/common/text_modal.html
new file mode 100644
index 00000000..0ae04a88
--- /dev/null
+++ b/web/html/common/text_modal.html
@@ -0,0 +1,58 @@
+{{define "textModal"}}
+<a-modal id="text-modal" v-model="txtModal.visible" :title="txtModal.title"
+ :closable="true" ok-text='{{ i18n "copy" }}' cancel-text='{{ i18n "close" }}'
+ :ok-button-props="{attrs:{id:'txt-modal-ok-btn'}}">
+ <a-button v-if="!ObjectUtil.isEmpty(txtModal.fileName)" type="primary" style="margin-bottom: 10px;"
+ @click="downloader.download(txtModal.fileName, txtModal.content)">
+ {{ i18n "download" }} [[ txtModal.fileName ]]
+ </a-button>
+ <a-input type="textarea" v-model="txtModal.content"
+ :autosize="{ minRows: 10, maxRows: 20}"></a-input>
+</a-modal>
+
+<script>
+
+ const txtModal = {
+ title: '',
+ content: '',
+ fileName: '',
+ qrcode: null,
+ clipboard: null,
+ visible: false,
+ show: function (title='', content='', fileName='') {
+ this.title = title;
+ this.content = content;
+ this.fileName = fileName;
+ this.visible = true;
+ textModalApp.$nextTick(() => {
+ if (this.clipboard === null) {
+ this.clipboard = new ClipboardJS('#txt-modal-ok-btn', {
+ text: () => this.content,
+ });
+ this.clipboard.on('success', () => app.$message.success('{{ i18n "copied" }}'));
+ }
+ if (this.qrcode === null) {
+ this.qrcode = new QRious({
+ element: document.querySelector('#qrCode'),
+ size: 260,
+ value: content,
+ });
+ } else {
+ this.qrcode.value = content;
+ }
+ });
+ },
+ close: function () {
+ this.visible = false;
+ },
+ };
+
+ const textModalApp = new Vue({
+ el: '#text-modal',
+ data: {
+ txtModal: txtModal,
+ },
+ });
+
+</script>
+{{end}} \ No newline at end of file