mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-01 12:32:09 +00:00
refactor: new loading logic, icons for tabs
Some checks failed
Release 3X-UI / build (386) (push) Has been cancelled
Release 3X-UI / build (amd64) (push) Has been cancelled
Release 3X-UI / build (arm64) (push) Has been cancelled
Release 3X-UI / build (armv5) (push) Has been cancelled
Release 3X-UI / build (armv6) (push) Has been cancelled
Release 3X-UI / build (armv7) (push) Has been cancelled
Release 3X-UI / build (s390x) (push) Has been cancelled
Some checks failed
Release 3X-UI / build (386) (push) Has been cancelled
Release 3X-UI / build (amd64) (push) Has been cancelled
Release 3X-UI / build (arm64) (push) Has been cancelled
Release 3X-UI / build (armv5) (push) Has been cancelled
Release 3X-UI / build (armv6) (push) Has been cancelled
Release 3X-UI / build (armv7) (push) Has been cancelled
Release 3X-UI / build (s390x) (push) Has been cancelled
This commit is contained in:
parent
d642774a44
commit
4b20f16024
5 changed files with 1979 additions and 1866 deletions
|
@ -148,9 +148,9 @@
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-spin :spinning="loadingStates.spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="showAlert && loadingStates.fetched" :style="{ marginBottom: '10px' }"
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
color="red"
|
color="red"
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
description='{{ i18n "secAlertSsl" }}'
|
||||||
|
@ -158,6 +158,13 @@
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
|
<a-row v-if="!loadingStates.fetched">
|
||||||
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
|
</a-card>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
|
<a-col>
|
||||||
<a-card size="small" :style="{ padding: '16px' }" hoverable>
|
<a-card size="small" :style="{ padding: '16px' }" hoverable>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :sm="12" :md="6">
|
<a-col :sm="12" :md="6">
|
||||||
|
@ -220,8 +227,8 @@
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
</transition>
|
</a-col>
|
||||||
<transition name="list" appear>
|
<a-col>
|
||||||
<a-card hoverable>
|
<a-card hoverable>
|
||||||
<template #title>
|
<template #title>
|
||||||
<a-space direction="horizontal">
|
<a-space direction="horizontal">
|
||||||
|
@ -651,6 +658,8 @@
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
</transition>
|
</transition>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
|
@ -766,7 +775,10 @@
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
persianDatepicker,
|
persianDatepicker,
|
||||||
spinning: false,
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
inbounds: [],
|
inbounds: [],
|
||||||
dbInbounds: [],
|
dbInbounds: [],
|
||||||
searchKey: '',
|
searchKey: '',
|
||||||
|
@ -797,7 +809,7 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning = true) {
|
loading(spinning = true) {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
},
|
},
|
||||||
getClientWithComment(email, inboundId) {
|
getClientWithComment(email, inboundId) {
|
||||||
const dbInbound = this.dbInbounds.find(inbound => inbound.id === inboundId);
|
const dbInbound = this.dbInbounds.find(inbound => inbound.id === inboundId);
|
||||||
|
@ -819,6 +831,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.getOnlineUsers();
|
await this.getOnlineUsers();
|
||||||
|
|
||||||
this.setInbounds(msg.obj);
|
this.setInbounds(msg.obj);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
|
@ -870,6 +883,9 @@
|
||||||
this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound);
|
this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true
|
||||||
|
}
|
||||||
if(this.enableFilter){
|
if(this.enableFilter){
|
||||||
this.filterInbounds();
|
this.filterInbounds();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1541,9 +1557,9 @@
|
||||||
},
|
},
|
||||||
async manualRefresh() {
|
async manualRefresh() {
|
||||||
if (!this.refreshing) {
|
if (!this.refreshing) {
|
||||||
this.spinning = true;
|
this.loadingStates.spinning = true;
|
||||||
await this.getDBInbounds();
|
await this.getDBInbounds();
|
||||||
this.spinning = false;
|
this.loadingStates.spinning = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pagination(obj){
|
pagination(obj){
|
||||||
|
|
|
@ -4,15 +4,6 @@
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
margin: 24px 16px;
|
margin: 24px 16px;
|
||||||
}
|
}
|
||||||
.ant-card-hoverable {
|
|
||||||
margin-inline: 0.3rem;
|
|
||||||
}
|
|
||||||
.ant-alert-error {
|
|
||||||
margin-inline: 0.3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-col-sm-24 {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
}
|
||||||
.ant-card-dark h2 {
|
.ant-card-dark h2 {
|
||||||
color: var(--dark-color-text-primary);
|
color: var(--dark-color-text-primary);
|
||||||
|
@ -84,9 +75,9 @@
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
<a-spin :spinning="loadingStates.spinning" :delay="200" :tip="loadingTip">
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="showAlert && loadingStates.fetched" :style="{ marginBottom: '10px' }"
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
color="red"
|
color="red"
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
description='{{ i18n "secAlertSsl" }}'
|
||||||
|
@ -95,15 +86,15 @@
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<template>
|
<template>
|
||||||
<a-row v-if="!status.isLoaded">
|
<a-row v-if="!loadingStates.fetched">
|
||||||
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row v-else>
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
<a-row>
|
<a-col>
|
||||||
<a-card hoverable>
|
<a-card hoverable>
|
||||||
<a-row>
|
<a-row :gutter="[0, isMobile ? 16 : 0]">
|
||||||
<a-col :sm="24" :md="12">
|
<a-col :sm="24" :md="12">
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
@ -153,7 +144,7 @@
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-row>
|
</a-col>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-col :sm="24" :lg="12">
|
||||||
<a-card hoverable>
|
<a-card hoverable>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -488,7 +479,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
class Status {
|
class Status {
|
||||||
constructor(data, isLoaded = false) {
|
constructor(data) {
|
||||||
this.cpu = new CurTotal(0, 0);
|
this.cpu = new CurTotal(0, 0);
|
||||||
this.cpuCores = 0;
|
this.cpuCores = 0;
|
||||||
this.logicalPro = 0;
|
this.logicalPro = 0;
|
||||||
|
@ -512,7 +503,6 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isLoaded = isLoaded;
|
|
||||||
this.cpu = new CurTotal(data.cpu, 100);
|
this.cpu = new CurTotal(data.cpu, 100);
|
||||||
this.cpuCores = data.cpuCores;
|
this.cpuCores = data.cpuCores;
|
||||||
this.logicalPro = data.logicalPro;
|
this.logicalPro = data.logicalPro;
|
||||||
|
@ -632,32 +622,39 @@
|
||||||
mixins: [MediaQueryMixin],
|
mixins: [MediaQueryMixin],
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
status: new Status(),
|
status: new Status(),
|
||||||
versionModal,
|
versionModal,
|
||||||
logModal,
|
logModal,
|
||||||
backupModal,
|
backupModal,
|
||||||
spinning: false,
|
|
||||||
loadingTip: '{{ i18n "loading"}}',
|
loadingTip: '{{ i18n "loading"}}',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
showIp: false
|
showIp: false
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning, tip = '{{ i18n "loading"}}') {
|
loading(spinning, tip = '{{ i18n "loading"}}') {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
this.loadingTip = tip;
|
this.loadingTip = tip;
|
||||||
},
|
},
|
||||||
async getStatus() {
|
async getStatus() {
|
||||||
try {
|
try {
|
||||||
const msg = await HttpUtil.post('/server/status');
|
const msg = await HttpUtil.post('/server/status');
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.setStatus(msg.obj, true);
|
this.setStatus(msg.obj, true);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to get status:", e);
|
console.error("Failed to get status:", e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setStatus(data, isLoaded = false) {
|
setStatus(data) {
|
||||||
this.status = new Status(data, isLoaded);
|
this.status = new Status(data);
|
||||||
},
|
},
|
||||||
async openSelectV2rayVersion() {
|
async openSelectV2rayVersion() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
|
|
|
@ -65,9 +65,9 @@
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-spin :spinning="loadingStates.spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="confAlerts.length>0" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="confAlerts.length>0 && loadingStates.fetched" :style="{ marginBottom: '10px' }"
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
color="red"
|
color="red"
|
||||||
show-icon closable>
|
show-icon closable>
|
||||||
|
@ -77,8 +77,16 @@
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</transition>
|
</transition>
|
||||||
<a-space direction="vertical">
|
<transition name="list" appear>
|
||||||
<a-card hoverable :style="{ marginBottom: '.5rem', overflowX: 'hidden' }">
|
<template>
|
||||||
|
<a-row v-if="!loadingStates.fetched">
|
||||||
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
|
</a-card>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
|
<a-col>
|
||||||
|
<a-card hoverable>
|
||||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||||
<a-space direction="horizontal">
|
<a-space direction="horizontal">
|
||||||
|
@ -99,24 +107,49 @@
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col>
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<a-tab-pane key="1" tab='{{ i18n "pages.settings.panelSettings" }}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="1" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="setting"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.panelSettings" }}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/panel/general" . }}
|
{{ template "settings/panel/general" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab='{{ i18n "pages.settings.securitySettings" }}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="2" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="safety"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.securitySettings" }}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/panel/security" . }}
|
{{ template "settings/panel/security" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" tab='{{ i18n "pages.settings.TGBotSettings" }}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="3" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="message"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.TGBotSettings" }}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/panel/telegram" . }}
|
{{ template "settings/panel/telegram" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="4" tab='{{ i18n "pages.settings.subSettings" }}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="4" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="cloud-server"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.subSettings" }}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/panel/subscription/general" . }}
|
{{ template "settings/panel/subscription/general" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" tab='{{ i18n "pages.settings.subSettings" }} Json' v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="5" v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="code"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.subSettings" }} (JSON)</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/panel/subscription/json" . }}
|
{{ template "settings/panel/subscription/json" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</a-space>
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</template>
|
||||||
|
</transition>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
|
@ -132,10 +165,14 @@
|
||||||
<script>
|
<script>
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
|
mixins: [MediaQueryMixin],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
spinning: false,
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
oldAllSetting: new AllSetting(),
|
oldAllSetting: new AllSetting(),
|
||||||
allSetting: new AllSetting(),
|
allSetting: new AllSetting(),
|
||||||
saveBtnDisable: true,
|
saveBtnDisable: true,
|
||||||
|
@ -248,13 +285,16 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning = true) {
|
loading(spinning = true) {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
},
|
},
|
||||||
async getAllSetting() {
|
async getAllSetting() {
|
||||||
this.loading(true);
|
|
||||||
const msg = await HttpUtil.post("/panel/setting/all");
|
const msg = await HttpUtil.post("/panel/setting/all");
|
||||||
this.loading(false);
|
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true
|
||||||
|
}
|
||||||
|
|
||||||
this.oldAllSetting = new AllSetting(msg.obj);
|
this.oldAllSetting = new AllSetting(msg.obj);
|
||||||
this.allSetting = new AllSetting(msg.obj);
|
this.allSetting = new AllSetting(msg.obj);
|
||||||
app.changeRemarkSample();
|
app.changeRemarkSample();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{{define "settings/xray/advanced"}}
|
{{define "settings/xray/advanced"}}
|
||||||
<a-space direction="vertical" size="small">
|
<a-space direction="vertical" size="small" :style="{ marginTop: '20px' }">
|
||||||
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}'
|
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}'
|
||||||
description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
||||||
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" :style="{ margin: '10px 0' }"
|
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" :style="{ margin: '10px 0' }"
|
||||||
|
|
|
@ -9,54 +9,67 @@
|
||||||
margin: 24px 16px;
|
margin: 24px 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.ant-tabs-nav .ant-tabs-tab {
|
.ant-tabs-nav .ant-tabs-tab {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 12px .5rem;
|
padding: 12px .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-thead>tr>th,
|
.ant-table-thead>tr>th,
|
||||||
.ant-table-tbody>tr>td {
|
.ant-table-tbody>tr>td {
|
||||||
padding: 10px 0px;
|
padding: 10px 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-tabs-bar {
|
.ant-tabs-bar {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-list-item {
|
.ant-list-item {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-list-item>li {
|
.ant-list-item>li {
|
||||||
padding: 10px 20px !important;
|
padding: 10px 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-collapse-content-box .ant-alert {
|
.ant-collapse-content-box .ant-alert {
|
||||||
margin-block-end: 12px;
|
margin-block-end: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{{ template "page/head_end" .}}
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
{{ template "page/body_start" .}}
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-spin :spinning="loadingStates.spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="showAlert && loadingStates.fetched" :style="{ marginBottom: '10px' }" message='{{ i18n "secAlertTitle" }}'
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
color="red" description='{{ i18n "secAlertSsl" }}' show-icon closable>
|
||||||
color="red"
|
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
|
||||||
show-icon closable>
|
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</transition>
|
</transition>
|
||||||
<a-space direction="vertical">
|
<transition name="list" appear>
|
||||||
<a-card hoverable :style="{ marginBottom: '.5rem' }">
|
<a-row v-if="!loadingStates.fetched">
|
||||||
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
|
</a-card>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
|
<a-col>
|
||||||
|
<a-card hoverable>
|
||||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||||
<a-space direction="horizontal">
|
<a-space direction="horizontal">
|
||||||
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">{{ i18n "pages.xray.save" }}</a-button>
|
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">
|
||||||
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">{{ i18n "pages.xray.restart" }}</a-button>
|
{{ i18n "pages.xray.save" }}
|
||||||
<a-popover v-if="restartResult"
|
</a-button>
|
||||||
:overlay-class-name="themeSwitcher.currentTheme">
|
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">
|
||||||
|
{{ i18n "pages.xray.restart" }}
|
||||||
|
</a-button>
|
||||||
|
<a-popover v-if="restartResult" :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
<span slot="title">{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
<span slot="title">{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<span :style="{ maxWidth: '400px' }" v-for="line in restartResult.split('\n')">[[ line ]]</span>
|
<span :style="{ maxWidth: '400px' }" v-for="line in restartResult.split('\n')">[[ line ]]</span>
|
||||||
|
@ -68,43 +81,76 @@
|
||||||
<a-col :xs="24" :sm="14">
|
<a-col :xs="24" :sm="14">
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
<a-back-top :target="() => document.getElementById('content-layout')"
|
||||||
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }" message='{{ i18n "pages.settings.infoDesc" }}' show-icon>
|
visibility-height="200"></a-back-top>
|
||||||
|
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }"
|
||||||
|
message='{{ i18n "pages.settings.infoDesc" }}' show-icon>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
<a-tabs class="ant-card-dark-box-nohover" default-active-key="1"
|
</a-col>
|
||||||
@change="(activeKey) => { this.changePage(activeKey); }"
|
<a-col>
|
||||||
|
<a-tabs default-active-key="tpl-basic" @change="(activeKey) => { this.changePage(activeKey); }"
|
||||||
:class="themeSwitcher.currentTheme">
|
:class="themeSwitcher.currentTheme">
|
||||||
<a-tab-pane key="tpl-basic" tab='{{ i18n "pages.xray.basicTemplate"}}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="tpl-basic" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="setting"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.basicTemplate"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/basics" . }}
|
{{ template "settings/xray/basics" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-routing" tab='{{ i18n "pages.xray.Routings"}}' :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="tpl-routing" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="swap"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.Routings"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/routing" . }}
|
{{ template "settings/xray/routing" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-outbound" tab='{{ i18n "pages.xray.Outbounds"}}' force-render="true">
|
<a-tab-pane key="tpl-outbound" force-render="true">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="upload"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.Outbounds"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/outbounds" . }}
|
{{ template "settings/xray/outbounds" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-reverse" tab='{{ i18n "pages.xray.outbound.reverse"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
<a-tab-pane key="tpl-reverse" :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="import"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.outbound.reverse"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/reverse" . }}
|
{{ template "settings/xray/reverse" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-balancer" tab='{{ i18n "pages.xray.Balancers"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
<a-tab-pane key="tpl-balancer" :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="cluster"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.Balancers"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/balancers" . }}
|
{{ template "settings/xray/balancers" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-dns" tab='DNS' :style="{ paddingTop: '20px' }" force-render="true">
|
<a-tab-pane key="tpl-dns" :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="database"></a-icon>
|
||||||
|
<span>DNS</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/dns" . }}
|
{{ template "settings/xray/dns" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
<a-tab-pane key="tpl-advanced" force-render="true">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="code"></a-icon>
|
||||||
|
<span>{{ i18n "pages.xray.advancedTemplate"}}</span>
|
||||||
|
</template>
|
||||||
{{ template "settings/xray/advanced" . }}
|
{{ template "settings/xray/advanced" . }}
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</a-space>
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</transition>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "page/body_scripts" .}}
|
{{template "page/body_scripts" .}}
|
||||||
<script src="{{ .base_path }}assets/js/model/outbound.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/outbound.js?{{ .cur_ver }}"></script>
|
||||||
|
@ -133,20 +179,28 @@
|
||||||
<script>
|
<script>
|
||||||
const rulesColumns = [
|
const rulesColumns = [
|
||||||
{ title: "#", align: 'center', width: 15, scopedSlots: { customRender: 'action' } },
|
{ title: "#", align: 'center', width: 15, scopedSlots: { customRender: 'action' } },
|
||||||
{ title: '{{ i18n "pages.xray.rules.source"}}', children: [
|
{
|
||||||
|
title: '{{ i18n "pages.xray.rules.source"}}', children: [
|
||||||
{ title: 'IP', dataIndex: "source", align: 'center', width: 20, ellipsis: true },
|
{ title: 'IP', dataIndex: "source", align: 'center', width: 20, ellipsis: true },
|
||||||
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'sourcePort', align: 'center', width: 10, ellipsis: true } ]},
|
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'sourcePort', align: 'center', width: 10, ellipsis: true }]
|
||||||
{ title: '{{ i18n "pages.inbounds.network"}}', children: [
|
},
|
||||||
|
{
|
||||||
|
title: '{{ i18n "pages.inbounds.network"}}', children: [
|
||||||
{ title: 'L4', dataIndex: 'network', align: 'center', width: 10 },
|
{ title: 'L4', dataIndex: 'network', align: 'center', width: 10 },
|
||||||
{ title: '{{ i18n "protocol" }}', dataIndex: 'protocol', align: 'center', width: 15, ellipsis: true },
|
{ title: '{{ i18n "protocol" }}', dataIndex: 'protocol', align: 'center', width: 15, ellipsis: true },
|
||||||
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 10, ellipsis: true } ]},
|
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 10, ellipsis: true }]
|
||||||
{ title: '{{ i18n "pages.xray.rules.dest"}}', children: [
|
},
|
||||||
|
{
|
||||||
|
title: '{{ i18n "pages.xray.rules.dest"}}', children: [
|
||||||
{ title: 'IP', dataIndex: 'ip', align: 'center', width: 20, ellipsis: true },
|
{ title: 'IP', dataIndex: 'ip', align: 'center', width: 20, ellipsis: true },
|
||||||
{ title: '{{ i18n "pages.xray.outbound.domain" }}', dataIndex: 'domain', align: 'center', width: 20, ellipsis: true },
|
{ title: '{{ i18n "pages.xray.outbound.domain" }}', dataIndex: 'domain', align: 'center', width: 20, ellipsis: true },
|
||||||
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]},
|
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]
|
||||||
{ title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
},
|
||||||
|
{
|
||||||
|
title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
||||||
{ title: '{{ i18n "pages.xray.outbound.tag" }}', dataIndex: 'inboundTag', align: 'center', width: 15, ellipsis: true },
|
{ title: '{{ i18n "pages.xray.outbound.tag" }}', dataIndex: 'inboundTag', align: 'center', width: 15, ellipsis: true },
|
||||||
{ title: '{{ i18n "pages.inbounds.client" }}', dataIndex: 'user', align: 'center', width: 20, ellipsis: true }]},
|
{ title: '{{ i18n "pages.inbounds.client" }}', dataIndex: 'user', align: 'center', width: 20, ellipsis: true }]
|
||||||
|
},
|
||||||
{ title: '{{ i18n "pages.xray.rules.outbound"}}', dataIndex: 'outboundTag', align: 'center', width: 17 },
|
{ title: '{{ i18n "pages.xray.rules.outbound"}}', dataIndex: 'outboundTag', align: 'center', width: 17 },
|
||||||
{ title: '{{ i18n "pages.xray.rules.balancer"}}', dataIndex: 'balancerTag', align: 'center', width: 15 },
|
{ title: '{{ i18n "pages.xray.rules.balancer"}}', dataIndex: 'balancerTag', align: 'center', width: 15 },
|
||||||
];
|
];
|
||||||
|
@ -176,8 +230,8 @@
|
||||||
const balancerColumns = [
|
const balancerColumns = [
|
||||||
{ title: "#", align: 'center', width: 20, scopedSlots: { customRender: 'action' } },
|
{ title: "#", align: 'center', width: 20, scopedSlots: { customRender: 'action' } },
|
||||||
{ title: '{{ i18n "pages.xray.balancer.tag"}}', dataIndex: 'tag', align: 'center', width: 50 },
|
{ title: '{{ i18n "pages.xray.balancer.tag"}}', dataIndex: 'tag', align: 'center', width: 50 },
|
||||||
{ title: '{{ i18n "pages.xray.balancer.balancerStrategy"}}', align: 'center', width: 50, scopedSlots: { customRender: 'strategy' }},
|
{ title: '{{ i18n "pages.xray.balancer.balancerStrategy"}}', align: 'center', width: 50, scopedSlots: { customRender: 'strategy' } },
|
||||||
{ title: '{{ i18n "pages.xray.balancer.balancerSelectors"}}', align: 'center', width: 100, scopedSlots: { customRender: 'selector' }},
|
{ title: '{{ i18n "pages.xray.balancer.balancerSelectors"}}', align: 'center', width: 100, scopedSlots: { customRender: 'selector' } },
|
||||||
];
|
];
|
||||||
|
|
||||||
const dnsColumns = [
|
const dnsColumns = [
|
||||||
|
@ -200,7 +254,10 @@
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
isDarkTheme: themeSwitcher.isDarkTheme,
|
isDarkTheme: themeSwitcher.isDarkTheme,
|
||||||
spinning: false,
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
oldXraySetting: '',
|
oldXraySetting: '',
|
||||||
xraySetting: '',
|
xraySetting: '',
|
||||||
inboundTags: [],
|
inboundTags: [],
|
||||||
|
@ -329,7 +386,7 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning = true) {
|
loading(spinning = true) {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
},
|
},
|
||||||
async getOutboundsTraffic() {
|
async getOutboundsTraffic() {
|
||||||
const msg = await HttpUtil.get("/panel/xray/getOutboundsTraffic");
|
const msg = await HttpUtil.get("/panel/xray/getOutboundsTraffic");
|
||||||
|
@ -338,10 +395,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getXraySetting() {
|
async getXraySetting() {
|
||||||
this.loading(true);
|
|
||||||
const msg = await HttpUtil.post("/panel/xray/");
|
const msg = await HttpUtil.post("/panel/xray/");
|
||||||
this.loading(false);
|
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true
|
||||||
|
}
|
||||||
|
|
||||||
result = JSON.parse(msg.obj);
|
result = JSON.parse(msg.obj);
|
||||||
xs = JSON.stringify(result.xraySetting, null, 2);
|
xs = JSON.stringify(result.xraySetting, null, 2);
|
||||||
this.oldXraySetting = xs;
|
this.oldXraySetting = xs;
|
||||||
|
@ -352,7 +412,7 @@
|
||||||
},
|
},
|
||||||
async updateXraySetting() {
|
async updateXraySetting() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
const msg = await HttpUtil.post("/panel/xray/update", {xraySetting : this.xraySetting});
|
const msg = await HttpUtil.post("/panel/xray/update", { xraySetting: this.xraySetting });
|
||||||
this.loading(false);
|
this.loading(false);
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
await this.getXraySetting();
|
await this.getXraySetting();
|
||||||
|
@ -371,8 +431,8 @@
|
||||||
async getXrayResult() {
|
async getXrayResult() {
|
||||||
const msg = await HttpUtil.get("/panel/xray/getXrayResult");
|
const msg = await HttpUtil.get("/panel/xray/getXrayResult");
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
this.restartResult=msg.obj;
|
this.restartResult = msg.obj;
|
||||||
if(msg.obj.length > 1) Vue.prototype.$message.error(msg.obj);
|
if (msg.obj.length > 1) Vue.prototype.$message.error(msg.obj);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async resetXrayConfigToDefault() {
|
async resetXrayConfigToDefault() {
|
||||||
|
@ -385,8 +445,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changePage(pageKey) {
|
changePage(pageKey) {
|
||||||
if(pageKey == 'tpl-advanced') this.changeCode();
|
if (pageKey == 'tpl-advanced') this.changeCode();
|
||||||
if(pageKey == 'tpl-balancer') this.changeObsCode();
|
if (pageKey == 'tpl-balancer') this.changeObsCode();
|
||||||
},
|
},
|
||||||
syncRulesWithOutbound(tag, setting) {
|
syncRulesWithOutbound(tag, setting) {
|
||||||
const newTemplateSettings = this.templateSettings;
|
const newTemplateSettings = this.templateSettings;
|
||||||
|
@ -457,13 +517,13 @@
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
},
|
},
|
||||||
changeCode() {
|
changeCode() {
|
||||||
if(this.cm != null) {
|
if (this.cm != null) {
|
||||||
this.cm.toTextArea();
|
this.cm.toTextArea();
|
||||||
}
|
}
|
||||||
textAreaObj = document.getElementById('xraySetting');
|
textAreaObj = document.getElementById('xraySetting');
|
||||||
textAreaObj.value = this[this.advSettings];
|
textAreaObj.value = this[this.advSettings];
|
||||||
this.cm = CodeMirror.fromTextArea(textAreaObj, this.cmOptions);
|
this.cm = CodeMirror.fromTextArea(textAreaObj, this.cmOptions);
|
||||||
this.cm.on('change',editor => {
|
this.cm.on('change', editor => {
|
||||||
value = editor.getValue();
|
value = editor.getValue();
|
||||||
if (this.isJsonString(value)) {
|
if (this.isJsonString(value)) {
|
||||||
this[this.advSettings] = value;
|
this[this.advSettings] = value;
|
||||||
|
@ -471,19 +531,19 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
changeObsCode() {
|
changeObsCode() {
|
||||||
if(this.cm != null) {
|
if (this.cm != null) {
|
||||||
this.cm.toTextArea();
|
this.cm.toTextArea();
|
||||||
}
|
}
|
||||||
if (this.obsSettings == ''){
|
if (this.obsSettings == '') {
|
||||||
this.cm = null;
|
this.cm = null;
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
textAreaObj = document.getElementById('obsSetting');
|
textAreaObj = document.getElementById('obsSetting');
|
||||||
textAreaObj.value = this[this.obsSettings];
|
textAreaObj.value = this[this.obsSettings];
|
||||||
this.cm = CodeMirror.fromTextArea(textAreaObj, this.cmOptions);
|
this.cm = CodeMirror.fromTextArea(textAreaObj, this.cmOptions);
|
||||||
this.cm.on('change',editor => {
|
this.cm.on('change', editor => {
|
||||||
value = editor.getValue();
|
value = editor.getValue();
|
||||||
if(this.isJsonString(value)){
|
if (this.isJsonString(value)) {
|
||||||
this[this.obsSettings] = value;
|
this[this.obsSettings] = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -506,7 +566,7 @@
|
||||||
},
|
},
|
||||||
findOutboundAddress(o) {
|
findOutboundAddress(o) {
|
||||||
serverObj = null;
|
serverObj = null;
|
||||||
switch(o.protocol){
|
switch (o.protocol) {
|
||||||
case Protocols.VMess:
|
case Protocols.VMess:
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
serverObj = o.settings.vnext;
|
serverObj = o.settings.vnext;
|
||||||
|
@ -526,13 +586,13 @@
|
||||||
}
|
}
|
||||||
return serverObj ? serverObj.map(obj => obj.address + ':' + obj.port) : null;
|
return serverObj ? serverObj.map(obj => obj.address + ':' + obj.port) : null;
|
||||||
},
|
},
|
||||||
addOutbound(){
|
addOutbound() {
|
||||||
outModal.show({
|
outModal.show({
|
||||||
title: '{{ i18n "pages.xray.outbound.addOutbound"}}',
|
title: '{{ i18n "pages.xray.outbound.addOutbound"}}',
|
||||||
okText: '{{ i18n "pages.xray.outbound.addOutbound" }}',
|
okText: '{{ i18n "pages.xray.outbound.addOutbound" }}',
|
||||||
confirm: (outbound) => {
|
confirm: (outbound) => {
|
||||||
outModal.loading();
|
outModal.loading();
|
||||||
if(outbound.tag.length > 0){
|
if (outbound.tag.length > 0) {
|
||||||
this.templateSettings.outbounds.push(outbound);
|
this.templateSettings.outbounds.push(outbound);
|
||||||
this.outboundSettings = JSON.stringify(this.templateSettings.outbounds);
|
this.outboundSettings = JSON.stringify(this.templateSettings.outbounds);
|
||||||
}
|
}
|
||||||
|
@ -542,9 +602,9 @@
|
||||||
tags: this.templateSettings.outbounds.map(obj => obj.tag)
|
tags: this.templateSettings.outbounds.map(obj => obj.tag)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
editOutbound(index){
|
editOutbound(index) {
|
||||||
outModal.show({
|
outModal.show({
|
||||||
title: '{{ i18n "pages.xray.outbound.editOutbound"}} ' + (index+1),
|
title: '{{ i18n "pages.xray.outbound.editOutbound"}} ' + (index + 1),
|
||||||
outbound: app.templateSettings.outbounds[index],
|
outbound: app.templateSettings.outbounds[index],
|
||||||
confirm: (outbound) => {
|
confirm: (outbound) => {
|
||||||
outModal.loading();
|
outModal.loading();
|
||||||
|
@ -553,30 +613,30 @@
|
||||||
outModal.close();
|
outModal.close();
|
||||||
},
|
},
|
||||||
isEdit: true,
|
isEdit: true,
|
||||||
tags: this.outboundData.filter((o) => o.key != index ).map(obj => obj.tag)
|
tags: this.outboundData.filter((o) => o.key != index).map(obj => obj.tag)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteOutbound(index){
|
deleteOutbound(index) {
|
||||||
outbounds = this.templateSettings.outbounds;
|
outbounds = this.templateSettings.outbounds;
|
||||||
outbounds.splice(index,1);
|
outbounds.splice(index, 1);
|
||||||
this.outboundSettings = JSON.stringify(outbounds);
|
this.outboundSettings = JSON.stringify(outbounds);
|
||||||
},
|
},
|
||||||
setFirstOutbound(index){
|
setFirstOutbound(index) {
|
||||||
outbounds = this.templateSettings.outbounds;
|
outbounds = this.templateSettings.outbounds;
|
||||||
outbounds.splice(0, 0, outbounds.splice(index, 1)[0]);
|
outbounds.splice(0, 0, outbounds.splice(index, 1)[0]);
|
||||||
this.outboundSettings = JSON.stringify(outbounds);
|
this.outboundSettings = JSON.stringify(outbounds);
|
||||||
},
|
},
|
||||||
addReverse(){
|
addReverse() {
|
||||||
reverseModal.show({
|
reverseModal.show({
|
||||||
title: '{{ i18n "pages.xray.outbound.addReverse"}}',
|
title: '{{ i18n "pages.xray.outbound.addReverse"}}',
|
||||||
okText: '{{ i18n "pages.xray.outbound.addReverse" }}',
|
okText: '{{ i18n "pages.xray.outbound.addReverse" }}',
|
||||||
confirm: (reverse, rules) => {
|
confirm: (reverse, rules) => {
|
||||||
reverseModal.loading();
|
reverseModal.loading();
|
||||||
if(reverse.tag.length > 0){
|
if (reverse.tag.length > 0) {
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
if(newTemplateSettings.reverse == undefined) newTemplateSettings.reverse = {};
|
if (newTemplateSettings.reverse == undefined) newTemplateSettings.reverse = {};
|
||||||
if(newTemplateSettings.reverse[reverse.type+'s'] == undefined) newTemplateSettings.reverse[reverse.type+'s'] = [];
|
if (newTemplateSettings.reverse[reverse.type + 's'] == undefined) newTemplateSettings.reverse[reverse.type + 's'] = [];
|
||||||
newTemplateSettings.reverse[reverse.type+'s'].push({ tag: reverse.tag, domain: reverse.domain });
|
newTemplateSettings.reverse[reverse.type + 's'].push({ tag: reverse.tag, domain: reverse.domain });
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
|
|
||||||
// Add related rules
|
// Add related rules
|
||||||
|
@ -588,33 +648,33 @@
|
||||||
isEdit: false
|
isEdit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
editReverse(index){
|
editReverse(index) {
|
||||||
if(this.reverseData[index].type == "bridge") {
|
if (this.reverseData[index].type == "bridge") {
|
||||||
oldRules = this.templateSettings.routing.rules.filter(r => r.inboundTag && r.inboundTag[0] == this.reverseData[index].tag);
|
oldRules = this.templateSettings.routing.rules.filter(r => r.inboundTag && r.inboundTag[0] == this.reverseData[index].tag);
|
||||||
} else {
|
} else {
|
||||||
oldRules = this.templateSettings.routing.rules.filter(r => r.outboundTag && r.outboundTag == this.reverseData[index].tag);
|
oldRules = this.templateSettings.routing.rules.filter(r => r.outboundTag && r.outboundTag == this.reverseData[index].tag);
|
||||||
}
|
}
|
||||||
reverseModal.show({
|
reverseModal.show({
|
||||||
title: '{{ i18n "pages.xray.outbound.editReverse"}} ' + (index+1),
|
title: '{{ i18n "pages.xray.outbound.editReverse"}} ' + (index + 1),
|
||||||
reverse: this.reverseData[index],
|
reverse: this.reverseData[index],
|
||||||
rules: oldRules,
|
rules: oldRules,
|
||||||
confirm: (reverse, rules) => {
|
confirm: (reverse, rules) => {
|
||||||
reverseModal.loading();
|
reverseModal.loading();
|
||||||
if(reverse.tag.length > 0){
|
if (reverse.tag.length > 0) {
|
||||||
oldData = this.reverseData[index];
|
oldData = this.reverseData[index];
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
oldReverseIndex = newTemplateSettings.reverse[oldData.type+'s'].findIndex(rs => rs.tag == oldData.tag);
|
oldReverseIndex = newTemplateSettings.reverse[oldData.type + 's'].findIndex(rs => rs.tag == oldData.tag);
|
||||||
oldRuleIndex0 = oldRules.length>0 ? newTemplateSettings.routing.rules.findIndex(r => JSON.stringify(r) == JSON.stringify(oldRules[0])) : -1;
|
oldRuleIndex0 = oldRules.length > 0 ? newTemplateSettings.routing.rules.findIndex(r => JSON.stringify(r) == JSON.stringify(oldRules[0])) : -1;
|
||||||
oldRuleIndex1 = oldRules.length==2 ? newTemplateSettings.routing.rules.findIndex(r => JSON.stringify(r) == JSON.stringify(oldRules[1])) : -1;
|
oldRuleIndex1 = oldRules.length == 2 ? newTemplateSettings.routing.rules.findIndex(r => JSON.stringify(r) == JSON.stringify(oldRules[1])) : -1;
|
||||||
if(oldData.type == reverse.type){
|
if (oldData.type == reverse.type) {
|
||||||
newTemplateSettings.reverse[oldData.type + 's'][oldReverseIndex] = { tag: reverse.tag, domain: reverse.domain };
|
newTemplateSettings.reverse[oldData.type + 's'][oldReverseIndex] = { tag: reverse.tag, domain: reverse.domain };
|
||||||
} else {
|
} else {
|
||||||
newTemplateSettings.reverse[oldData.type+'s'].splice(oldReverseIndex,1);
|
newTemplateSettings.reverse[oldData.type + 's'].splice(oldReverseIndex, 1);
|
||||||
// delete empty object
|
// delete empty object
|
||||||
if(newTemplateSettings.reverse[oldData.type+'s'].length == 0) Reflect.deleteProperty(newTemplateSettings.reverse, oldData.type+'s');
|
if (newTemplateSettings.reverse[oldData.type + 's'].length == 0) Reflect.deleteProperty(newTemplateSettings.reverse, oldData.type + 's');
|
||||||
// add other type of reverse if it is not exist
|
// add other type of reverse if it is not exist
|
||||||
if(!newTemplateSettings.reverse[reverse.type+'s']) newTemplateSettings.reverse[reverse.type+'s'] = [];
|
if (!newTemplateSettings.reverse[reverse.type + 's']) newTemplateSettings.reverse[reverse.type + 's'] = [];
|
||||||
newTemplateSettings.reverse[reverse.type+'s'].push({ tag: reverse.tag, domain: reverse.domain });
|
newTemplateSettings.reverse[reverse.type + 's'].push({ tag: reverse.tag, domain: reverse.domain });
|
||||||
}
|
}
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
|
|
||||||
|
@ -629,22 +689,22 @@
|
||||||
isEdit: true
|
isEdit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteReverse(index){
|
deleteReverse(index) {
|
||||||
oldData = this.reverseData[index];
|
oldData = this.reverseData[index];
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
reverseTypeObj = newTemplateSettings.reverse[oldData.type+'s'];
|
reverseTypeObj = newTemplateSettings.reverse[oldData.type + 's'];
|
||||||
realIndex = reverseTypeObj.findIndex(r => r.tag==oldData.tag && r.domain==oldData.domain);
|
realIndex = reverseTypeObj.findIndex(r => r.tag == oldData.tag && r.domain == oldData.domain);
|
||||||
newTemplateSettings.reverse[oldData.type+'s'].splice(realIndex,1);
|
newTemplateSettings.reverse[oldData.type + 's'].splice(realIndex, 1);
|
||||||
|
|
||||||
// delete empty objects
|
// delete empty objects
|
||||||
if(reverseTypeObj.length == 0) Reflect.deleteProperty(newTemplateSettings.reverse, oldData.type+'s');
|
if (reverseTypeObj.length == 0) Reflect.deleteProperty(newTemplateSettings.reverse, oldData.type + 's');
|
||||||
if(Object.keys(newTemplateSettings.reverse).length === 0) Reflect.deleteProperty(newTemplateSettings, 'reverse');
|
if (Object.keys(newTemplateSettings.reverse).length === 0) Reflect.deleteProperty(newTemplateSettings, 'reverse');
|
||||||
|
|
||||||
// delete related routing rules
|
// delete related routing rules
|
||||||
newRules = newTemplateSettings.routing.rules;
|
newRules = newTemplateSettings.routing.rules;
|
||||||
if(oldData.type == "bridge"){
|
if (oldData.type == "bridge") {
|
||||||
newRules = newTemplateSettings.routing.rules.filter(r => !( r.inboundTag && r.inboundTag.length == 1 && r.inboundTag[0] == oldData.tag));
|
newRules = newTemplateSettings.routing.rules.filter(r => !(r.inboundTag && r.inboundTag.length == 1 && r.inboundTag[0] == oldData.tag));
|
||||||
} else if(oldData.type == "portal"){
|
} else if (oldData.type == "portal") {
|
||||||
newRules = newTemplateSettings.routing.rules.filter(r => r.outboundTag != oldData.tag);
|
newRules = newTemplateSettings.routing.rules.filter(r => r.outboundTag != oldData.tag);
|
||||||
}
|
}
|
||||||
newTemplateSettings.routing.rules = newRules;
|
newTemplateSettings.routing.rules = newRules;
|
||||||
|
@ -659,7 +719,7 @@
|
||||||
data = []
|
data = []
|
||||||
if (this.templateSettings != null) {
|
if (this.templateSettings != null) {
|
||||||
this.templateSettings.outbounds.forEach((o, index) => {
|
this.templateSettings.outbounds.forEach((o, index) => {
|
||||||
data.push({'key': index, ...o});
|
data.push({ 'key': index, ...o });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,10 +791,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove old tag
|
// Remove old tag
|
||||||
if (newTemplateSettings.observatory){
|
if (newTemplateSettings.observatory) {
|
||||||
newTemplateSettings.observatory.subjectSelector = newTemplateSettings.observatory.subjectSelector.filter(s => s != oldTag);
|
newTemplateSettings.observatory.subjectSelector = newTemplateSettings.observatory.subjectSelector.filter(s => s != oldTag);
|
||||||
}
|
}
|
||||||
if (newTemplateSettings.burstObservatory){
|
if (newTemplateSettings.burstObservatory) {
|
||||||
newTemplateSettings.burstObservatory.subjectSelector = newTemplateSettings.burstObservatory.subjectSelector.filter(s => s != oldTag);
|
newTemplateSettings.burstObservatory.subjectSelector = newTemplateSettings.burstObservatory.subjectSelector.filter(s => s != oldTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +821,7 @@
|
||||||
isEdit: true
|
isEdit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateObservatorySelectors(){
|
updateObservatorySelectors() {
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
const leastPings = this.balancersData.filter((b) => b.strategy == 'leastPing');
|
const leastPings = this.balancersData.filter((b) => b.strategy == 'leastPing');
|
||||||
const leastLoads = this.balancersData.filter((b) =>
|
const leastLoads = this.balancersData.filter((b) =>
|
||||||
|
@ -769,7 +829,7 @@
|
||||||
b.strategy === 'roundRobin' ||
|
b.strategy === 'roundRobin' ||
|
||||||
b.strategy === 'random'
|
b.strategy === 'random'
|
||||||
);
|
);
|
||||||
if (leastPings.length>0){
|
if (leastPings.length > 0) {
|
||||||
if (!newTemplateSettings.observatory)
|
if (!newTemplateSettings.observatory)
|
||||||
newTemplateSettings.observatory = this.defaultObservatory;
|
newTemplateSettings.observatory = this.defaultObservatory;
|
||||||
newTemplateSettings.observatory.subjectSelector = [];
|
newTemplateSettings.observatory.subjectSelector = [];
|
||||||
|
@ -782,7 +842,7 @@
|
||||||
} else {
|
} else {
|
||||||
delete newTemplateSettings.observatory
|
delete newTemplateSettings.observatory
|
||||||
}
|
}
|
||||||
if (leastLoads.length>0){
|
if (leastLoads.length > 0) {
|
||||||
if (!newTemplateSettings.burstObservatory)
|
if (!newTemplateSettings.burstObservatory)
|
||||||
newTemplateSettings.burstObservatory = this.defaultBurstObservatory;
|
newTemplateSettings.burstObservatory = this.defaultBurstObservatory;
|
||||||
newTemplateSettings.burstObservatory.subjectSelector = [];
|
newTemplateSettings.burstObservatory.subjectSelector = [];
|
||||||
|
@ -827,7 +887,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
addDNSServer(){
|
addDNSServer() {
|
||||||
dnsModal.show({
|
dnsModal.show({
|
||||||
title: '{{ i18n "pages.xray.dns.add" }}',
|
title: '{{ i18n "pages.xray.dns.add" }}',
|
||||||
confirm: (dnsServer) => {
|
confirm: (dnsServer) => {
|
||||||
|
@ -839,9 +899,9 @@
|
||||||
isEdit: false
|
isEdit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
editDNSServer(index){
|
editDNSServer(index) {
|
||||||
dnsModal.show({
|
dnsModal.show({
|
||||||
title: '{{ i18n "pages.xray.dns.edit" }} #' + (index+1),
|
title: '{{ i18n "pages.xray.dns.edit" }} #' + (index + 1),
|
||||||
dnsServer: this.dnsServers[index],
|
dnsServer: this.dnsServers[index],
|
||||||
confirm: (dnsServer) => {
|
confirm: (dnsServer) => {
|
||||||
dnsServers = this.dnsServers;
|
dnsServers = this.dnsServers;
|
||||||
|
@ -852,16 +912,16 @@
|
||||||
isEdit: true
|
isEdit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteDNSServer(index){
|
deleteDNSServer(index) {
|
||||||
newDnsServers = this.dnsServers;
|
newDnsServers = this.dnsServers;
|
||||||
newDnsServers.splice(index,1);
|
newDnsServers.splice(index, 1);
|
||||||
this.dnsServers = newDnsServers;
|
this.dnsServers = newDnsServers;
|
||||||
},
|
},
|
||||||
addFakedns() {
|
addFakedns() {
|
||||||
fakednsModal.show({
|
fakednsModal.show({
|
||||||
title: '{{ i18n "pages.xray.fakedns.add" }}',
|
title: '{{ i18n "pages.xray.fakedns.add" }}',
|
||||||
confirm: (item) => {
|
confirm: (item) => {
|
||||||
fakeDns = this.fakeDns?? [];
|
fakeDns = this.fakeDns ?? [];
|
||||||
fakeDns.push(item);
|
fakeDns.push(item);
|
||||||
this.fakeDns = fakeDns;
|
this.fakeDns = fakeDns;
|
||||||
fakednsModal.close();
|
fakednsModal.close();
|
||||||
|
@ -869,9 +929,9 @@
|
||||||
isEdit: false
|
isEdit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
editFakedns(index){
|
editFakedns(index) {
|
||||||
fakednsModal.show({
|
fakednsModal.show({
|
||||||
title: '{{ i18n "pages.xray.fakedns.edit" }} #' + (index+1),
|
title: '{{ i18n "pages.xray.fakedns.edit" }} #' + (index + 1),
|
||||||
fakeDns: this.fakeDns[index],
|
fakeDns: this.fakeDns[index],
|
||||||
confirm: (item) => {
|
confirm: (item) => {
|
||||||
fakeDns = this.fakeDns;
|
fakeDns = this.fakeDns;
|
||||||
|
@ -882,18 +942,18 @@
|
||||||
isEdit: true
|
isEdit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteFakedns(index){
|
deleteFakedns(index) {
|
||||||
fakeDns = this.fakeDns;
|
fakeDns = this.fakeDns;
|
||||||
fakeDns.splice(index,1);
|
fakeDns.splice(index, 1);
|
||||||
this.fakeDns = fakeDns;
|
this.fakeDns = fakeDns;
|
||||||
},
|
},
|
||||||
addRule(){
|
addRule() {
|
||||||
ruleModal.show({
|
ruleModal.show({
|
||||||
title: '{{ i18n "pages.xray.rules.add"}}',
|
title: '{{ i18n "pages.xray.rules.add"}}',
|
||||||
okText: '{{ i18n "pages.xray.rules.add" }}',
|
okText: '{{ i18n "pages.xray.rules.add" }}',
|
||||||
confirm: (rule) => {
|
confirm: (rule) => {
|
||||||
ruleModal.loading();
|
ruleModal.loading();
|
||||||
if(JSON.stringify(rule).length > 3){
|
if (JSON.stringify(rule).length > 3) {
|
||||||
this.templateSettings.routing.rules.push(rule);
|
this.templateSettings.routing.rules.push(rule);
|
||||||
this.routingRuleSettings = JSON.stringify(this.templateSettings.routing.rules);
|
this.routingRuleSettings = JSON.stringify(this.templateSettings.routing.rules);
|
||||||
}
|
}
|
||||||
|
@ -902,13 +962,13 @@
|
||||||
isEdit: false
|
isEdit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
editRule(index){
|
editRule(index) {
|
||||||
ruleModal.show({
|
ruleModal.show({
|
||||||
title: '{{ i18n "pages.xray.rules.edit"}} ' + (index+1),
|
title: '{{ i18n "pages.xray.rules.edit"}} ' + (index + 1),
|
||||||
rule: app.templateSettings.routing.rules[index],
|
rule: app.templateSettings.routing.rules[index],
|
||||||
confirm: (rule) => {
|
confirm: (rule) => {
|
||||||
ruleModal.loading();
|
ruleModal.loading();
|
||||||
if(JSON.stringify(rule).length > 3){
|
if (JSON.stringify(rule).length > 3) {
|
||||||
this.templateSettings.routing.rules[index] = rule;
|
this.templateSettings.routing.rules[index] = rule;
|
||||||
this.routingRuleSettings = JSON.stringify(this.templateSettings.routing.rules);
|
this.routingRuleSettings = JSON.stringify(this.templateSettings.routing.rules);
|
||||||
}
|
}
|
||||||
|
@ -917,18 +977,18 @@
|
||||||
isEdit: true
|
isEdit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
replaceRule(old_index,new_index){
|
replaceRule(old_index, new_index) {
|
||||||
rules = this.templateSettings.routing.rules;
|
rules = this.templateSettings.routing.rules;
|
||||||
if (new_index >= rules.length) rules.push(undefined);
|
if (new_index >= rules.length) rules.push(undefined);
|
||||||
rules.splice(new_index, 0, rules.splice(old_index, 1)[0]);
|
rules.splice(new_index, 0, rules.splice(old_index, 1)[0]);
|
||||||
this.routingRuleSettings = JSON.stringify(rules);
|
this.routingRuleSettings = JSON.stringify(rules);
|
||||||
},
|
},
|
||||||
deleteRule(index){
|
deleteRule(index) {
|
||||||
rules = this.templateSettings.routing.rules;
|
rules = this.templateSettings.routing.rules;
|
||||||
rules.splice(index,1);
|
rules.splice(index, 1);
|
||||||
this.routingRuleSettings = JSON.stringify(rules);
|
this.routingRuleSettings = JSON.stringify(rules);
|
||||||
},
|
},
|
||||||
showWarp(){
|
showWarp() {
|
||||||
warpModal.show();
|
warpModal.show();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -977,7 +1037,7 @@
|
||||||
data = []
|
data = []
|
||||||
if (this.templateSettings != null) {
|
if (this.templateSettings != null) {
|
||||||
this.templateSettings.outbounds.forEach((o, index) => {
|
this.templateSettings.outbounds.forEach((o, index) => {
|
||||||
data.push({'key': index, ...o});
|
data.push({ 'key': index, ...o });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
|
@ -987,14 +1047,14 @@
|
||||||
get: function () {
|
get: function () {
|
||||||
data = []
|
data = []
|
||||||
if (this.templateSettings != null && this.templateSettings.reverse != null) {
|
if (this.templateSettings != null && this.templateSettings.reverse != null) {
|
||||||
if(this.templateSettings.reverse.bridges) {
|
if (this.templateSettings.reverse.bridges) {
|
||||||
this.templateSettings.reverse.bridges.forEach((o, index) => {
|
this.templateSettings.reverse.bridges.forEach((o, index) => {
|
||||||
data.push({'key': index, 'type':'bridge', ...o});
|
data.push({ 'key': index, 'type': 'bridge', ...o });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(this.templateSettings.reverse.portals){
|
if (this.templateSettings.reverse.portals) {
|
||||||
this.templateSettings.reverse.portals.forEach((o, index) => {
|
this.templateSettings.reverse.portals.forEach((o, index) => {
|
||||||
data.push({'key': index, 'type':'portal', ...o});
|
data.push({ 'key': index, 'type': 'portal', ...o });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1014,17 +1074,17 @@
|
||||||
data = [];
|
data = [];
|
||||||
if (this.templateSettings != null) {
|
if (this.templateSettings != null) {
|
||||||
this.templateSettings.routing.rules.forEach((r, index) => {
|
this.templateSettings.routing.rules.forEach((r, index) => {
|
||||||
data.push({'key': index, ...r});
|
data.push({ 'key': index, ...r });
|
||||||
});
|
});
|
||||||
// Make rules readable
|
// Make rules readable
|
||||||
data.forEach(r => {
|
data.forEach(r => {
|
||||||
if(r.domain) r.domain = r.domain.join(',')
|
if (r.domain) r.domain = r.domain.join(',')
|
||||||
if(r.ip) r.ip = r.ip.join(',')
|
if (r.ip) r.ip = r.ip.join(',')
|
||||||
if(r.source) r.source = r.source.join(',');
|
if (r.source) r.source = r.source.join(',');
|
||||||
if(r.user) r.user = r.user.join(',')
|
if (r.user) r.user = r.user.join(',')
|
||||||
if(r.inboundTag) r.inboundTag = r.inboundTag.join(',')
|
if (r.inboundTag) r.inboundTag = r.inboundTag.join(',')
|
||||||
if(r.protocol) r.protocol = r.protocol.join(',')
|
if (r.protocol) r.protocol = r.protocol.join(',')
|
||||||
if(r.attrs) r.attrs = JSON.stringify(r.attrs, null, 2)
|
if (r.attrs) r.attrs = JSON.stringify(r.attrs, null, 2)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
|
@ -1040,7 +1100,7 @@
|
||||||
'tag': o.tag ? o.tag : "",
|
'tag': o.tag ? o.tag : "",
|
||||||
'strategy': o.strategy?.type ?? "random",
|
'strategy': o.strategy?.type ?? "random",
|
||||||
'selector': o.selector ? o.selector : [],
|
'selector': o.selector ? o.selector : [],
|
||||||
'fallbackTag': o.fallbackTag?? '',
|
'fallbackTag': o.fallbackTag ?? '',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1080,10 +1140,10 @@
|
||||||
set: function (newValue) {
|
set: function (newValue) {
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
freedomOutboundIndex = newTemplateSettings.outbounds.findIndex((o) => o.protocol === "freedom" && o.tag == "direct");
|
freedomOutboundIndex = newTemplateSettings.outbounds.findIndex((o) => o.protocol === "freedom" && o.tag == "direct");
|
||||||
if(freedomOutboundIndex == -1){
|
if (freedomOutboundIndex == -1) {
|
||||||
newTemplateSettings.outbounds.push({protocol: "freedom", tag: "direct", settings: { "domainStrategy": newValue }});
|
newTemplateSettings.outbounds.push({ protocol: "freedom", tag: "direct", settings: { "domainStrategy": newValue } });
|
||||||
} else if (!newTemplateSettings.outbounds[freedomOutboundIndex].settings) {
|
} else if (!newTemplateSettings.outbounds[freedomOutboundIndex].settings) {
|
||||||
newTemplateSettings.outbounds[freedomOutboundIndex].settings = {"domainStrategy": newValue};
|
newTemplateSettings.outbounds[freedomOutboundIndex].settings = { "domainStrategy": newValue };
|
||||||
} else {
|
} else {
|
||||||
newTemplateSettings.outbounds[freedomOutboundIndex].settings.domainStrategy = newValue;
|
newTemplateSettings.outbounds[freedomOutboundIndex].settings.domainStrategy = newValue;
|
||||||
}
|
}
|
||||||
|
@ -1272,8 +1332,8 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
WarpExist: {
|
WarpExist: {
|
||||||
get: function() {
|
get: function () {
|
||||||
return this.templateSettings ? this.templateSettings.outbounds.findIndex((o) => o.tag == "warp")>=0 : false;
|
return this.templateSettings ? this.templateSettings.outbounds.findIndex((o) => o.tag == "warp") >= 0 : false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
enableDNS: {
|
enableDNS: {
|
||||||
|
|
Loading…
Reference in a new issue