mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-20 05:52:24 +00:00
Manage balancers in settings UI (#1759)
* add balancer config to ui * manage balancer in rules table * fix balancer translations * fix edit button text
This commit is contained in:
parent
222b9734ca
commit
c53cee31f5
9 changed files with 363 additions and 3 deletions
|
@ -327,6 +327,14 @@
|
||||||
[[ rule.outboundTag ]]
|
[[ rule.outboundTag ]]
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
|
<template slot="balancer" slot-scope="text, rule, index">
|
||||||
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
|
<template slot="content">
|
||||||
|
<p v-if="rule.balancerTag">Balancer Tag: [[ rule.balancerTag ]]</p>
|
||||||
|
</template>
|
||||||
|
[[ rule.balancerTag ]]
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
<template slot="info" slot-scope="text, rule, index">
|
<template slot="info" slot-scope="text, rule, index">
|
||||||
<a-popover placement="bottomRight"
|
<a-popover placement="bottomRight"
|
||||||
v-if="(rule.source+rule.sourcePort+rule.network+rule.protocol+rule.attrs+rule.ip+rule.domain+rule.port).length>0"
|
v-if="(rule.source+rule.sourcePort+rule.network+rule.protocol+rule.attrs+rule.ip+rule.domain+rule.port).length>0"
|
||||||
|
@ -452,6 +460,41 @@
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="tpl-balancers" tab='{{ i18n "pages.xray.Balancers"}}' style="padding-top: 20px;" force-render="true">
|
||||||
|
<a-button type="primary" icon="plus" @click="addBalancer()" style="margin-bottom: 10px;">{{ i18n "pages.xray.balancer.addBalancer"}}</a-button>
|
||||||
|
<a-table :columns="balancerColumns" bordered
|
||||||
|
:row-key="r => r.key"
|
||||||
|
:data-source="balancersData"
|
||||||
|
:scroll="isMobile ? {} : { x: 200 }"
|
||||||
|
:pagination="false"
|
||||||
|
:indent-size="0"
|
||||||
|
:style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'">
|
||||||
|
<template slot="action" slot-scope="text, balancer, index">
|
||||||
|
[[ index+1 ]]
|
||||||
|
<a-dropdown :trigger="['click']">
|
||||||
|
<a-icon @click="e => e.preventDefault()" type="more" style="font-size: 16px; text-decoration: bold;"></a-icon>
|
||||||
|
<a-menu slot="overlay" :theme="themeSwitcher.currentTheme">
|
||||||
|
<a-menu-item @click="editBalancer(index)">
|
||||||
|
<a-icon type="edit"></a-icon>
|
||||||
|
{{ i18n "edit" }}
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item @click="deleteBalancer(index)">
|
||||||
|
<span style="color: #FF4D4F">
|
||||||
|
<a-icon type="delete"></a-icon> {{ i18n "delete"}}
|
||||||
|
</span>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
<template slot="strategy" slot-scope="text, balancer, index">
|
||||||
|
<a-tag style="margin:0;" v-if="balancer.strategy=='random'" color="purple">Random</a-tag>
|
||||||
|
<a-tag style="margin:0;" v-if="balancer.strategy=='roundRobin'" color="green">Round Robin</a-tag>
|
||||||
|
</template>
|
||||||
|
<template slot="selector" slot-scope="text, balancer, index">
|
||||||
|
<a-tag class="info-large-tag" style="margin:1;" v-for="sel in balancer.selector">[[ sel ]]</a-tag>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' style="padding-top: 20px;" force-render="true">
|
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' style="padding-top: 20px;" force-render="true">
|
||||||
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}' description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}' description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
||||||
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" style="margin: 10px 0;" :size="isMobile ? 'small' : ''">
|
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" style="margin: 10px 0;" :size="isMobile ? 'small' : ''">
|
||||||
|
@ -474,6 +517,7 @@
|
||||||
{{template "ruleModal"}}
|
{{template "ruleModal"}}
|
||||||
{{template "outModal"}}
|
{{template "outModal"}}
|
||||||
{{template "reverseModal"}}
|
{{template "reverseModal"}}
|
||||||
|
{{template "balancerModal"}}
|
||||||
{{template "warpModal"}}
|
{{template "warpModal"}}
|
||||||
<script>
|
<script>
|
||||||
const rulesColumns = [
|
const rulesColumns = [
|
||||||
|
@ -490,9 +534,10 @@
|
||||||
{ title: 'Domain', dataIndex: 'domain', align: 'center', width: 20, ellipsis: true },
|
{ title: 'Domain', dataIndex: 'domain', align: 'center', width: 20, ellipsis: true },
|
||||||
{ title: 'Port', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]},
|
{ title: 'Port', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]},
|
||||||
{ title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
{ title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
||||||
{ title: 'Inbound Tag', dataIndex: 'inboundTag', align: 'center', width: 20, ellipsis: true },
|
{ title: 'Inbound Tag', dataIndex: 'inboundTag', align: 'center', width: 15, ellipsis: true },
|
||||||
{ title: 'Client Email', dataIndex: 'user', align: 'center', width: 20, ellipsis: true }]},
|
{ title: 'Client Email', dataIndex: 'user', align: 'center', width: 20, ellipsis: true }]},
|
||||||
{ title: '{{ i18n "pages.xray.rules.outbound"}}', dataIndex: 'outboundTag', align: 'center', width: 20 },
|
{ title: '{{ i18n "pages.xray.rules.outbound"}}', dataIndex: 'outboundTag', align: 'center', width: 15 },
|
||||||
|
{ title: '{{ i18n "pages.xray.rules.balancer"}}', dataIndex: 'balancerTag', align: 'center', width: 15 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rulesMobileColumns = [
|
const rulesMobileColumns = [
|
||||||
|
@ -517,6 +562,13 @@
|
||||||
{ title: '{{ i18n "pages.xray.outbound.domain"}}', dataIndex: 'domain', align: 'center', width: 50 },
|
{ title: '{{ i18n "pages.xray.outbound.domain"}}', dataIndex: 'domain', align: 'center', width: 50 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const balancerColumns = [
|
||||||
|
{ 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.balancerStrategy"}}', align: 'center', width: 50, scopedSlots: { customRender: 'strategy' }},
|
||||||
|
{ title: '{{ i18n "pages.xray.balancer.balancerSelectors"}}', align: 'center', width: 100, scopedSlots: { customRender: 'selector' }},
|
||||||
|
];
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
|
@ -895,6 +947,95 @@
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addBalancer() {
|
||||||
|
balancerModal.show({
|
||||||
|
title: '{{ i18n "pages.xray.balancer.addBalancer"}}',
|
||||||
|
okText: '{{ i18n "pages.xray.balancer.addBalancer"}}',
|
||||||
|
balancerTags: this.balancersData.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag),
|
||||||
|
balancer: {
|
||||||
|
tag: '',
|
||||||
|
strategy: 'random',
|
||||||
|
selector: []
|
||||||
|
},
|
||||||
|
confirm: (balancer) => {
|
||||||
|
balancerModal.loading();
|
||||||
|
newTemplateSettings = this.templateSettings;
|
||||||
|
if (newTemplateSettings.routing.balancers == undefined) {
|
||||||
|
newTemplateSettings.routing.balancers = [];
|
||||||
|
}
|
||||||
|
let tmpBalancer = {
|
||||||
|
'tag': balancer.tag,
|
||||||
|
'selector': balancer.selector
|
||||||
|
};
|
||||||
|
if (balancer.strategy == 'roundRobin') {
|
||||||
|
tmpBalancer.strategy = {
|
||||||
|
'type': balancer.strategy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
newTemplateSettings.routing.balancers.push(tmpBalancer);
|
||||||
|
this.templateSettings = newTemplateSettings;
|
||||||
|
balancerModal.close();
|
||||||
|
},
|
||||||
|
isEdit: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
editBalancer(index) {
|
||||||
|
const oldTag = this.balancersData[index].tag;
|
||||||
|
balancerModal.show({
|
||||||
|
title: '{{ i18n "pages.xray.balancer.editBalancer"}}',
|
||||||
|
okText: '{{ i18n "sure" }}',
|
||||||
|
balancerTags: this.balancersData.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag),
|
||||||
|
balancer: this.balancersData[index],
|
||||||
|
confirm: (balancer) => {
|
||||||
|
balancerModal.loading();
|
||||||
|
newTemplateSettings = this.templateSettings;
|
||||||
|
|
||||||
|
let tmpBalancer = {
|
||||||
|
'tag': balancer.tag,
|
||||||
|
'selector': balancer.selector
|
||||||
|
};
|
||||||
|
if (balancer.strategy == 'roundRobin') {
|
||||||
|
tmpBalancer.strategy = {
|
||||||
|
'type': balancer.strategy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
newTemplateSettings.routing.balancers[index] = tmpBalancer;
|
||||||
|
// change edited tag if used in rule section
|
||||||
|
if (oldTag != balancer.tag) {
|
||||||
|
newTemplateSettings.routing.rules.forEach((rule) => {
|
||||||
|
if (rule.balancerTag && rule.balancerTag == oldTag) {
|
||||||
|
rule.balancerTag = balancer.tag;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.templateSettings = newTemplateSettings;
|
||||||
|
balancerModal.close();
|
||||||
|
},
|
||||||
|
isEdit: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
deleteBalancer(index) {
|
||||||
|
newTemplateSettings = this.templateSettings;
|
||||||
|
|
||||||
|
//remove from balancers
|
||||||
|
const oldTag = this.balancersData[index].tag;
|
||||||
|
this.balancersData.splice(index, 1);
|
||||||
|
|
||||||
|
// remove from settings
|
||||||
|
let realIndex = newTemplateSettings.routing.balancers.findIndex((b) => b.tag == oldTag);
|
||||||
|
newTemplateSettings.routing.balancers.splice(realIndex, 1);
|
||||||
|
|
||||||
|
// remove related routing rules
|
||||||
|
let rules = [];
|
||||||
|
newTemplateSettings.routing.rules.forEach((r) => {
|
||||||
|
if (!r.balancerTag || r.balancerTag != oldTag) {
|
||||||
|
rules.push(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newTemplateSettings.routing.rules = rules;
|
||||||
|
this.templateSettings = newTemplateSettings;
|
||||||
|
},
|
||||||
addReverse(){
|
addReverse(){
|
||||||
reverseModal.show({
|
reverseModal.show({
|
||||||
title: '{{ i18n "pages.xray.outbound.addReverse"}}',
|
title: '{{ i18n "pages.xray.outbound.addReverse"}}',
|
||||||
|
@ -1084,6 +1225,27 @@
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
balancersData: {
|
||||||
|
get: function () {
|
||||||
|
data = []
|
||||||
|
if (this.templateSettings != null && this.templateSettings.routing != null && this.templateSettings.routing.balancers != null) {
|
||||||
|
this.templateSettings.routing.balancers.forEach((o, index) => {
|
||||||
|
let strategy = "random"
|
||||||
|
if (o.strategy && o.strategy.type == "roundRobin") {
|
||||||
|
strategy = o.strategy.type
|
||||||
|
}
|
||||||
|
|
||||||
|
data.push({
|
||||||
|
'key': index,
|
||||||
|
'tag': o.tag ? o.tag : "",
|
||||||
|
'strategy': strategy,
|
||||||
|
'selector': o.selector ? o.selector : []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
},
|
||||||
routingRuleSettings: {
|
routingRuleSettings: {
|
||||||
get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.routing.rules, null, 2) : null; },
|
get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.routing.rules, null, 2) : null; },
|
||||||
set: function (newValue) {
|
set: function (newValue) {
|
||||||
|
|
111
web/html/xui/xray_balancer_modal.html
Normal file
111
web/html/xui/xray_balancer_modal.html
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
{{define "balancerModal"}}
|
||||||
|
<a-modal
|
||||||
|
id="balancer-modal"
|
||||||
|
v-model="balancerModal.visible"
|
||||||
|
:title="balancerModal.title"
|
||||||
|
@ok="balancerModal.ok"
|
||||||
|
:confirm-loading="balancerModal.confirmLoading"
|
||||||
|
:ok-button-props="{ props: { disabled: !balancerModal.isValid } }"
|
||||||
|
:closable="true"
|
||||||
|
:mask-closable="false"
|
||||||
|
:ok-text="balancerModal.okText"
|
||||||
|
cancel-text='{{ i18n "close" }}'
|
||||||
|
:class="themeSwitcher.currentTheme">
|
||||||
|
<a-form :colon="false" :label-col="{ md: {span:6} }" :wrapper-col="{ md: {span:14} }">
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.balancer.tag" }}' has-feedback
|
||||||
|
:validate-status="balancerModal.duplicateTag? 'warning' : 'success'">
|
||||||
|
<a-input v-model.trim="balancerModal.balancer.tag" @change="balancerModal.check()"
|
||||||
|
placeholder='{{ i18n "balancerModal.balancer.tagDesc" }}'></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.balancer.balancerStrategy" }}'>
|
||||||
|
<a-select v-model="balancerModal.balancer.strategy" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="random">Random</a-select-option>
|
||||||
|
<a-select-option value="roundRobin">Round Robin</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.balancer.balancerSelectors" }}' has-feedback :validate-status="balancerModal.emptySelector? 'warning' : 'success'">
|
||||||
|
<a-select v-model="balancerModal.balancer.selector" mode="tags" @change="balancerModal.checkSelector()"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="tag in balancerModal.outboundTags" :value="tag">[[ tag ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</table>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
<script>
|
||||||
|
const balancerModal = {
|
||||||
|
title: '',
|
||||||
|
visible: false,
|
||||||
|
confirmLoading: false,
|
||||||
|
okText: '{{ i18n "sure" }}',
|
||||||
|
isEdit: false,
|
||||||
|
confirm: null,
|
||||||
|
duplicateTag: false,
|
||||||
|
emptySelector: false,
|
||||||
|
balancer: {
|
||||||
|
tag: '',
|
||||||
|
strategy: 'random',
|
||||||
|
selector: []
|
||||||
|
},
|
||||||
|
outboundTags: [],
|
||||||
|
balancerTags:[],
|
||||||
|
ok() {
|
||||||
|
if (balancerModal.balancer.selector.length == 0) {
|
||||||
|
balancerModal.emptySelector = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
balancerModal.emptySelector = false;
|
||||||
|
ObjectUtil.execute(balancerModal.confirm, balancerModal.balancer);
|
||||||
|
},
|
||||||
|
show({ title = '', okText = '{{ i18n "sure" }}', balancerTags = [], balancer, confirm = (balancer) => { }, isEdit = false }) {
|
||||||
|
this.title = title;
|
||||||
|
this.okText = okText;
|
||||||
|
this.confirm = confirm;
|
||||||
|
this.visible = true;
|
||||||
|
if (isEdit) {
|
||||||
|
balancerModal.balancer = balancer;
|
||||||
|
} else {
|
||||||
|
balancerModal.balancer = {
|
||||||
|
tag: '',
|
||||||
|
strategy: 'random',
|
||||||
|
selector: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.balancerTags = balancerTags.filter((tag) => tag != balancer.tag);
|
||||||
|
this.outboundTags = app.templateSettings.outbounds.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag);
|
||||||
|
this.isEdit = isEdit;
|
||||||
|
this.check()
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
balancerModal.visible = false;
|
||||||
|
balancerModal.loading(false);
|
||||||
|
},
|
||||||
|
loading(loading) {
|
||||||
|
balancerModal.confirmLoading = loading;
|
||||||
|
},
|
||||||
|
check() {
|
||||||
|
if (balancerModal.balancer.tag == '' || balancerModal.balancerTags.includes(balancerModal.balancer.tag)) {
|
||||||
|
this.duplicateTag = true;
|
||||||
|
this.isValid = false;
|
||||||
|
} else {
|
||||||
|
this.duplicateTag = false;
|
||||||
|
this.isValid = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkSelector() {
|
||||||
|
balancerModal.emptySelector = balancerModal.balancer.selector.length == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
delimiters: ['[[', ']]'],
|
||||||
|
el: '#balancer-modal',
|
||||||
|
data: {
|
||||||
|
balancerModal: balancerModal
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{{end}}
|
|
@ -107,6 +107,19 @@
|
||||||
<a-select-option v-for="tag in ruleModal.outboundTags" :value="tag">[[ tag ]]</a-select-option>
|
<a-select-option v-for="tag in ruleModal.outboundTags" :value="tag">[[ tag ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<template slot="label">
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.xray.balancer.balancerDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
Balancer Tag <a-icon type="question-circle"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-select v-model="ruleModal.rule.balancerTag" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="tag in ruleModal.balancerTags" :value="tag">[[ tag ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
</table>
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
@ -133,11 +146,12 @@
|
||||||
protocol: [],
|
protocol: [],
|
||||||
attrs: [],
|
attrs: [],
|
||||||
outboundTag: "",
|
outboundTag: "",
|
||||||
|
balancerTag: "",
|
||||||
},
|
},
|
||||||
inboundTags: [],
|
inboundTags: [],
|
||||||
outboundTags: [],
|
outboundTags: [],
|
||||||
users: [],
|
users: [],
|
||||||
balancerTag: [],
|
balancerTags: [],
|
||||||
ok() {
|
ok() {
|
||||||
newRule = ruleModal.getResult();
|
newRule = ruleModal.getResult();
|
||||||
ObjectUtil.execute(ruleModal.confirm, newRule);
|
ObjectUtil.execute(ruleModal.confirm, newRule);
|
||||||
|
@ -160,6 +174,7 @@
|
||||||
this.rule.protocol = rule.protocol;
|
this.rule.protocol = rule.protocol;
|
||||||
this.rule.attrs = rule.attrs ? Object.entries(rule.attrs) : [];
|
this.rule.attrs = rule.attrs ? Object.entries(rule.attrs) : [];
|
||||||
this.rule.outboundTag = rule.outboundTag;
|
this.rule.outboundTag = rule.outboundTag;
|
||||||
|
this.rule.balancerTag = rule.balancerTag ? rule.balancerTag : ""
|
||||||
} else {
|
} else {
|
||||||
this.rule = {
|
this.rule = {
|
||||||
domainMatcher: "",
|
domainMatcher: "",
|
||||||
|
@ -174,6 +189,7 @@
|
||||||
protocol: [],
|
protocol: [],
|
||||||
attrs: [],
|
attrs: [],
|
||||||
outboundTag: "",
|
outboundTag: "",
|
||||||
|
balancerTag: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.isEdit = isEdit;
|
this.isEdit = isEdit;
|
||||||
|
@ -186,6 +202,10 @@
|
||||||
}
|
}
|
||||||
if(app.templateSettings.reverse.portals) this.outboundTags.push(...app.templateSettings.reverse.portals.map(b => b.tag));
|
if(app.templateSettings.reverse.portals) this.outboundTags.push(...app.templateSettings.reverse.portals.map(b => b.tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (app.templateSettings.routing && app.templateSettings.routing.balancers) {
|
||||||
|
this.balancerTags = app.templateSettings.routing.balancers.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
ruleModal.visible = false;
|
ruleModal.visible = false;
|
||||||
|
@ -211,6 +231,7 @@
|
||||||
rule.protocol = value.protocol;
|
rule.protocol = value.protocol;
|
||||||
rule.attrs = Object.fromEntries(value.attrs);
|
rule.attrs = Object.fromEntries(value.attrs);
|
||||||
rule.outboundTag = value.outboundTag;
|
rule.outboundTag = value.outboundTag;
|
||||||
|
rule.balancerTag = value.balancerTag;
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(rule)) {
|
for (const [key, value] of Object.entries(rule)) {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "Inbounds"
|
"Inbounds" = "Inbounds"
|
||||||
"InboundsDesc" = "Accepting the specific clients."
|
"InboundsDesc" = "Accepting the specific clients."
|
||||||
"Outbounds" = "Outbounds"
|
"Outbounds" = "Outbounds"
|
||||||
|
"Balancers" = "Balancers"
|
||||||
"OutboundsDesc" = "Set the outgoing traffic pathway."
|
"OutboundsDesc" = "Set the outgoing traffic pathway."
|
||||||
"Routings" = "Routing Rules"
|
"Routings" = "Routing Rules"
|
||||||
"RoutingsDesc" = "The priority of each rule is important!"
|
"RoutingsDesc" = "The priority of each rule is important!"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "Destination"
|
"dest" = "Destination"
|
||||||
"inbound" = "Inbound"
|
"inbound" = "Inbound"
|
||||||
"outbound" = "Outbound"
|
"outbound" = "Outbound"
|
||||||
|
"balancer" = "Balancer"
|
||||||
"info" = "Info"
|
"info" = "Info"
|
||||||
"add" = "Add Rule"
|
"add" = "Add Rule"
|
||||||
"edit" = "Edit Rule"
|
"edit" = "Edit Rule"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "Portal"
|
"portal" = "Portal"
|
||||||
"intercon" = "Interconnection"
|
"intercon" = "Interconnection"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "Add Balancer"
|
||||||
|
"editBalancer" = "Edit Balancer"
|
||||||
|
"balancerStrategy" = "Strategy"
|
||||||
|
"balancerSelectors" = "Selectors"
|
||||||
|
"tag" = "Tag"
|
||||||
|
"tagDesc" = "Unique Tag"
|
||||||
|
"balancerDesc" = "It is not possible to use balancerTag and outboundTag at the same time. If used at the same time, only outboundTag will work."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "Secret Key"
|
"secretKey" = "Secret Key"
|
||||||
"publicKey" = "Public Key"
|
"publicKey" = "Public Key"
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "Entrante"
|
"Inbounds" = "Entrante"
|
||||||
"InboundsDesc" = "Cambia la plantilla de configuración para aceptar clientes específicos."
|
"InboundsDesc" = "Cambia la plantilla de configuración para aceptar clientes específicos."
|
||||||
"Outbounds" = "Salidas"
|
"Outbounds" = "Salidas"
|
||||||
|
"Balancers" = "Equilibradores"
|
||||||
"OutboundsDesc" = "Cambia la plantilla de configuración para definir formas de salida para este servidor."
|
"OutboundsDesc" = "Cambia la plantilla de configuración para definir formas de salida para este servidor."
|
||||||
"Routings" = "Reglas de enrutamiento"
|
"Routings" = "Reglas de enrutamiento"
|
||||||
"RoutingsDesc" = "¡La prioridad de cada regla es importante!"
|
"RoutingsDesc" = "¡La prioridad de cada regla es importante!"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "Destino"
|
"dest" = "Destino"
|
||||||
"inbound" = "Entrante"
|
"inbound" = "Entrante"
|
||||||
"outbound" = "saliente"
|
"outbound" = "saliente"
|
||||||
|
"balancer" = "Balancín"
|
||||||
"info" = "Información"
|
"info" = "Información"
|
||||||
"add" = "Agregar regla"
|
"add" = "Agregar regla"
|
||||||
"edit" = "Editar regla"
|
"edit" = "Editar regla"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "portal"
|
"portal" = "portal"
|
||||||
"intercon" = "Interconexión"
|
"intercon" = "Interconexión"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "Agregar equilibrador"
|
||||||
|
"editBalancer" = "Editar balanceador"
|
||||||
|
"balancerStrategy" = "Estrategia"
|
||||||
|
"balancerSelectors" = "Selectores"
|
||||||
|
"tag" = "Etiqueta"
|
||||||
|
"tagDesc" = "etiqueta única"
|
||||||
|
"balancerDesc" = "No es posible utilizar balancerTag y outboundTag al mismo tiempo. Si se utilizan al mismo tiempo, sólo funcionará outboundTag."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "Llave secreta"
|
"secretKey" = "Llave secreta"
|
||||||
"publicKey" = "Llave pública"
|
"publicKey" = "Llave pública"
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "ورودیها"
|
"Inbounds" = "ورودیها"
|
||||||
"InboundsDesc" = "پذیرش کلاینت خاص"
|
"InboundsDesc" = "پذیرش کلاینت خاص"
|
||||||
"Outbounds" = "خروجیها"
|
"Outbounds" = "خروجیها"
|
||||||
|
"Balancers" = "بالانسرها"
|
||||||
"OutboundsDesc" = "مسیر ترافیک خروجی را تنظیم کنید"
|
"OutboundsDesc" = "مسیر ترافیک خروجی را تنظیم کنید"
|
||||||
"Routings" = "قوانین مسیریابی"
|
"Routings" = "قوانین مسیریابی"
|
||||||
"RoutingsDesc" = "اولویت هر قانون مهم است"
|
"RoutingsDesc" = "اولویت هر قانون مهم است"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "مقصد"
|
"dest" = "مقصد"
|
||||||
"inbound" = "ورودی"
|
"inbound" = "ورودی"
|
||||||
"outbound" = "خروجی"
|
"outbound" = "خروجی"
|
||||||
|
"balancer" = "بالانسر"
|
||||||
"info" = "اطلاعات"
|
"info" = "اطلاعات"
|
||||||
"add" = "افزودن قانون"
|
"add" = "افزودن قانون"
|
||||||
"edit" = "ویرایش قانون"
|
"edit" = "ویرایش قانون"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "پورتال"
|
"portal" = "پورتال"
|
||||||
"intercon" = "اتصال میانی"
|
"intercon" = "اتصال میانی"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "افزودن بالانسر"
|
||||||
|
"editBalancer" = "ویرایش بالانسر"
|
||||||
|
"balancerStrategy" = "استراتژی"
|
||||||
|
"balancerSelectors" = "انتخابگرها"
|
||||||
|
"tag" = "برچسب"
|
||||||
|
"tagDesc" = "برچسب یگانه"
|
||||||
|
"balancerDesc" = "امکان استفاده همزمان balancerTag و outboundTag باهم وجود ندارد. درصورت استفاده همزمان فقط outboundTag عمل خواهد کرد."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "کلید شخصی"
|
"secretKey" = "کلید شخصی"
|
||||||
"publicKey" = "کلید عمومی"
|
"publicKey" = "کلید عمومی"
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "Входящие"
|
"Inbounds" = "Входящие"
|
||||||
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных пользователей"
|
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных пользователей"
|
||||||
"Outbounds" = "Исходящие"
|
"Outbounds" = "Исходящие"
|
||||||
|
"Balancers" = "Балансиры"
|
||||||
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие пути для этого сервера"
|
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие пути для этого сервера"
|
||||||
"Routings" = "Правила маршрутизации"
|
"Routings" = "Правила маршрутизации"
|
||||||
"RoutingsDesc" = "Важен приоритет каждого правила!"
|
"RoutingsDesc" = "Важен приоритет каждого правила!"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "Пункт назначения"
|
"dest" = "Пункт назначения"
|
||||||
"inbound" = "Входящий"
|
"inbound" = "Входящий"
|
||||||
"outbound" = "Исходящий"
|
"outbound" = "Исходящий"
|
||||||
|
"balancer" = "балансир"
|
||||||
"info" = "Информация"
|
"info" = "Информация"
|
||||||
"add" = "Добавить правило"
|
"add" = "Добавить правило"
|
||||||
"edit" = "Редактировать правило"
|
"edit" = "Редактировать правило"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "Портал"
|
"portal" = "Портал"
|
||||||
"intercon" = "Соединение"
|
"intercon" = "Соединение"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "Добавить балансир"
|
||||||
|
"editBalancer" = "Редактировать балансир"
|
||||||
|
"balancerStrategy" = "Стратегия"
|
||||||
|
"balancerSelectors" = "Селекторы"
|
||||||
|
"tag" = "Тег"
|
||||||
|
"tagDesc" = "уникальный тег"
|
||||||
|
"balancerDesc" = "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "Секретный ключ"
|
"secretKey" = "Секретный ключ"
|
||||||
"publicKey" = "Открытый ключ"
|
"publicKey" = "Открытый ключ"
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "Đầu vào"
|
"Inbounds" = "Đầu vào"
|
||||||
"InboundsDesc" = "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể."
|
"InboundsDesc" = "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể."
|
||||||
"Outbounds" = "Đầu ra"
|
"Outbounds" = "Đầu ra"
|
||||||
|
"Balancers" = "Cân bằng"
|
||||||
"OutboundsDesc" = "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này."
|
"OutboundsDesc" = "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này."
|
||||||
"Routings" = "Quy tắc định tuyến"
|
"Routings" = "Quy tắc định tuyến"
|
||||||
"RoutingsDesc" = "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!"
|
"RoutingsDesc" = "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "Đích"
|
"dest" = "Đích"
|
||||||
"inbound" = "Vào"
|
"inbound" = "Vào"
|
||||||
"outbound" = "Ra"
|
"outbound" = "Ra"
|
||||||
|
"balancer" = "Cân bằng"
|
||||||
"info" = "Thông tin"
|
"info" = "Thông tin"
|
||||||
"add" = "Thêm quy tắc"
|
"add" = "Thêm quy tắc"
|
||||||
"edit" = "Chỉnh sửa quy tắc"
|
"edit" = "Chỉnh sửa quy tắc"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "Cổng thông tin"
|
"portal" = "Cổng thông tin"
|
||||||
"intercon" = "Kết nối"
|
"intercon" = "Kết nối"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "Thêm cân bằng"
|
||||||
|
"editBalancer" = "Chỉnh sửa cân bằng"
|
||||||
|
"balancerStrategy" = "Chiến lược"
|
||||||
|
"balancerSelectors" = "Bộ chọn"
|
||||||
|
"tag" = "Thẻ"
|
||||||
|
"tagDesc" = "thẻ duy nhất"
|
||||||
|
"balancerDesc" = "Không thể sử dụng balancerTag và outboundTag cùng một lúc. Nếu sử dụng cùng lúc thì chỉ outboundTag mới hoạt động."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "Khoá bí mật"
|
"secretKey" = "Khoá bí mật"
|
||||||
"publicKey" = "Khóa công khai"
|
"publicKey" = "Khóa công khai"
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
"Inbounds" = "入站"
|
"Inbounds" = "入站"
|
||||||
"InboundsDesc" = "更改配置模板接受特殊客户端"
|
"InboundsDesc" = "更改配置模板接受特殊客户端"
|
||||||
"Outbounds" = "出站"
|
"Outbounds" = "出站"
|
||||||
|
"Balancers" = "平衡器"
|
||||||
"OutboundsDesc" = "更改配置模板定义此服务器的传出方式"
|
"OutboundsDesc" = "更改配置模板定义此服务器的传出方式"
|
||||||
"Routings" = "路由规则"
|
"Routings" = "路由规则"
|
||||||
"RoutingsDesc" = "每条规则的优先级都很重要"
|
"RoutingsDesc" = "每条规则的优先级都很重要"
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dest" = "目的地"
|
"dest" = "目的地"
|
||||||
"inbound" = "入站"
|
"inbound" = "入站"
|
||||||
"outbound" = "出站"
|
"outbound" = "出站"
|
||||||
|
"balancer" = "平衡器"
|
||||||
"info" = "信息"
|
"info" = "信息"
|
||||||
"add" = "添加规则"
|
"add" = "添加规则"
|
||||||
"edit" = "编辑规则"
|
"edit" = "编辑规则"
|
||||||
|
@ -426,6 +428,15 @@
|
||||||
"portal" = "门户"
|
"portal" = "门户"
|
||||||
"intercon" = "互连"
|
"intercon" = "互连"
|
||||||
|
|
||||||
|
[pages.xray.balancer]
|
||||||
|
"addBalancer" = "添加平衡器"
|
||||||
|
"editBalancer" = "编辑平衡器"
|
||||||
|
"balancerStrategy" = "战略"
|
||||||
|
"balancerSelectors" = "选择器"
|
||||||
|
"tag" = "标签"
|
||||||
|
"tagDesc" = "唯一标记"
|
||||||
|
"balancerDesc" = "不能同时使用balancerTag和outboundTag。 如果同时使用,则只有outboundTag起作用。"
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "密钥"
|
"secretKey" = "密钥"
|
||||||
"publicKey" = "公钥"
|
"publicKey" = "公钥"
|
||||||
|
|
Loading…
Reference in a new issue