mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-07 10:46:19 +00:00
Merge cd83708c17
into bbcab768ca
This commit is contained in:
commit
cdc9231929
24 changed files with 1521 additions and 162 deletions
|
@ -20,6 +20,7 @@ type SubService struct {
|
||||||
address string
|
address string
|
||||||
showInfo bool
|
showInfo bool
|
||||||
remarkModel string
|
remarkModel string
|
||||||
|
datepicker string
|
||||||
inboundService service.InboundService
|
inboundService service.InboundService
|
||||||
settingService service.SettingService
|
settingService service.SettingService
|
||||||
}
|
}
|
||||||
|
@ -39,6 +40,10 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.remarkModel = "-ieo"
|
s.remarkModel = "-ieo"
|
||||||
}
|
}
|
||||||
|
s.datepicker, err = s.settingService.GetDatepicker()
|
||||||
|
if err != nil {
|
||||||
|
s.datepicker = "gregorian"
|
||||||
|
}
|
||||||
for _, inbound := range inbounds {
|
for _, inbound := range inbounds {
|
||||||
clients, err := s.inboundService.GetClients(inbound)
|
clients, err := s.inboundService.GetClients(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,6 +12,7 @@ class AllSetting {
|
||||||
this.expireDiff = "";
|
this.expireDiff = "";
|
||||||
this.trafficDiff = "";
|
this.trafficDiff = "";
|
||||||
this.remarkModel = "-ieo";
|
this.remarkModel = "-ieo";
|
||||||
|
this.datepicker = "gregorian";
|
||||||
this.tgBotEnable = false;
|
this.tgBotEnable = false;
|
||||||
this.tgBotToken = "";
|
this.tgBotToken = "";
|
||||||
this.tgBotChatId = "";
|
this.tgBotChatId = "";
|
||||||
|
|
1252
web/assets/moment/moment-jalali.min.js
vendored
Normal file
1252
web/assets/moment/moment-jalali.min.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
web/assets/persian-datepicker/persian-datepicker.min.css
vendored
Normal file
1
web/assets/persian-datepicker/persian-datepicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
web/assets/persian-datepicker/persian-datepicker.min.js
vendored
Normal file
1
web/assets/persian-datepicker/persian-datepicker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -47,6 +47,7 @@ type AllSetting struct {
|
||||||
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
|
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
|
||||||
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
|
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
|
||||||
SubURI string `json:"subURI" form:"subURI"`
|
SubURI string `json:"subURI" form:"subURI"`
|
||||||
|
Datepicker string `json:"datepicker" form:"datepicker"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AllSetting) CheckValid() error {
|
func (s *AllSetting) CheckValid() error {
|
||||||
|
|
|
@ -104,8 +104,10 @@
|
||||||
<a-icon type="question-circle"></a-icon>
|
<a-icon type="question-circle"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
<a-date-picker v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme" v-model="clientsBulkModal.expiryTime"></a-date-picker>
|
:dropdown-class-name="themeSwitcher.currentTheme" v-model="clientsBulkModal.expiryTime"></a-date-picker>
|
||||||
|
<persian-datepicker v-else :dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
|
value="clientsBulkModal.expiryTime" v-model="clientsBulkModal.expiryTime"></persian-datepicker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="clientsBulkModal.expiryTime != 0">
|
<a-form-item v-if="clientsBulkModal.expiryTime != 0">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
|
@ -234,6 +236,9 @@
|
||||||
get delayedExpireDays() {
|
get delayedExpireDays() {
|
||||||
return this.clientsBulkModal.expiryTime < 0 ? this.clientsBulkModal.expiryTime / -86400000 : 0;
|
return this.clientsBulkModal.expiryTime < 0 ? this.clientsBulkModal.expiryTime / -86400000 : 0;
|
||||||
},
|
},
|
||||||
|
get datepicker() {
|
||||||
|
return app.datepicker;
|
||||||
|
},
|
||||||
set delayedExpireDays(days) {
|
set delayedExpireDays(days) {
|
||||||
this.clientsBulkModal.expiryTime = -86400000 * days;
|
this.clientsBulkModal.expiryTime = -86400000 * days;
|
||||||
},
|
},
|
||||||
|
|
|
@ -94,6 +94,9 @@
|
||||||
get isEdit() {
|
get isEdit() {
|
||||||
return this.clientModal.isEdit;
|
return this.clientModal.isEdit;
|
||||||
},
|
},
|
||||||
|
get datepicker() {
|
||||||
|
return app.datepicker;
|
||||||
|
},
|
||||||
get isTrafficExhausted() {
|
get isTrafficExhausted() {
|
||||||
if (!clientStats) return false
|
if (!clientStats) return false
|
||||||
if (clientStats.total <= 0) return false
|
if (clientStats.total <= 0) return false
|
||||||
|
|
59
web/html/xui/component/persianDatepicker.html
Normal file
59
web/html/xui/component/persianDatepicker.html
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{{define "component/persianDatepickerTemplate"}}
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-input :value="value" type="text" v-model="date" data-jdp class="persian-datepicker"
|
||||||
|
@input="$emit('input', convertToGregorian($event.target.value)); jalaliDatepicker.hide();"
|
||||||
|
placeholder="انتخاب تاریخ">
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-icon type="calendar" style="font-size: 16px;"/>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "component/persianDatepicker"}}
|
||||||
|
<link rel="stylesheet" href="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.css"/>
|
||||||
|
<script src="{{ .base_path }}assets/moment/moment-jalali.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const persianDatepicker = {};
|
||||||
|
|
||||||
|
Vue.component('persian-datepicker', {
|
||||||
|
props: ['dropdown-class-name', 'format', 'value'],
|
||||||
|
template: `{{template "component/persianDatepickerTemplate"}}`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
date: '',
|
||||||
|
persianDatepicker,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: function (date) {
|
||||||
|
this.date = this.convertToJalalian(date)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.date = this.convertToJalalian(this.value)
|
||||||
|
this.listenToDatepicker()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
convertToGregorian(date) {
|
||||||
|
return date ? moment(moment(date, 'jYYYY/jMM/jDD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')) : null
|
||||||
|
},
|
||||||
|
convertToJalalian(date) {
|
||||||
|
return date && moment.isMoment(date) ? date.format('jYYYY/jMM/jDD HH:mm:ss') : null
|
||||||
|
},
|
||||||
|
listenToDatepicker() {
|
||||||
|
jalaliDatepicker.startWatch({
|
||||||
|
time: true,
|
||||||
|
hideAfterChange: true,
|
||||||
|
useDropDownYears: false,
|
||||||
|
changeMonthRotateYear: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{end}}
|
|
@ -150,8 +150,10 @@
|
||||||
<a-icon type="question-circle"></a-icon>
|
<a-icon type="question-circle"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
<a-date-picker v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme" v-model="client._expiryTime"></a-date-picker>
|
:dropdown-class-name="themeSwitcher.currentTheme" v-model="client._expiryTime"></a-date-picker>
|
||||||
|
<persian-datepicker v-else :dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
|
value="client._expiryTime" v-model="client._expiryTime"></persian-datepicker>
|
||||||
<a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag>
|
<a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="client.expiryTime != 0">
|
<a-form-item v-if="client.expiryTime != 0">
|
||||||
|
|
|
@ -54,9 +54,11 @@
|
||||||
<a-icon type="question-circle"></a-icon>
|
<a-icon type="question-circle"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
<a-date-picker v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
v-model="dbInbound._expiryTime"></a-date-picker>
|
v-model="dbInbound._expiryTime"></a-date-picker>
|
||||||
|
<persian-datepicker v-else :dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
|
value="dbInbound._expiryTime" v-model="dbInbound._expiryTime"></persian-datepicker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,9 @@
|
||||||
get client() {
|
get client() {
|
||||||
return inModal.inbound.clients[0];
|
return inModal.inbound.clients[0];
|
||||||
},
|
},
|
||||||
|
get datepicker() {
|
||||||
|
return app.datepicker;
|
||||||
|
},
|
||||||
get delayedExpireDays() {
|
get delayedExpireDays() {
|
||||||
return this.client && this.client.expiryTime < 0 ? this.client.expiryTime / -86400000 : 0;
|
return this.client && this.client.expiryTime < 0 ? this.client.expiryTime / -86400000 : 0;
|
||||||
},
|
},
|
||||||
|
|
|
@ -446,6 +446,7 @@
|
||||||
<script src="{{ .base_path }}assets/js/model/xray.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/xray.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/js/model/dbinbound.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/dbinbound.js?{{ .cur_ver }}"></script>
|
||||||
{{template "component/themeSwitcher" .}}
|
{{template "component/themeSwitcher" .}}
|
||||||
|
{{template "component/persianDatepicker" .}}
|
||||||
<script>
|
<script>
|
||||||
const columns = [{
|
const columns = [{
|
||||||
title: "ID",
|
title: "ID",
|
||||||
|
@ -539,6 +540,7 @@
|
||||||
data: {
|
data: {
|
||||||
siderDrawer,
|
siderDrawer,
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
|
persianDatepicker,
|
||||||
spinning: false,
|
spinning: false,
|
||||||
inbounds: [],
|
inbounds: [],
|
||||||
dbInbounds: [],
|
dbInbounds: [],
|
||||||
|
@ -560,6 +562,7 @@
|
||||||
subURI : ''
|
subURI : ''
|
||||||
},
|
},
|
||||||
remarkModel: '-ieo',
|
remarkModel: '-ieo',
|
||||||
|
datepicker: 'gregorian',
|
||||||
tgBotEnable: false,
|
tgBotEnable: false,
|
||||||
pageSize: 0,
|
pageSize: 0,
|
||||||
isMobile: window.innerWidth <= 768,
|
isMobile: window.innerWidth <= 768,
|
||||||
|
@ -605,6 +608,7 @@
|
||||||
};
|
};
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
this.remarkModel = remarkModel;
|
this.remarkModel = remarkModel;
|
||||||
|
this.datepicker = datepicker;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setInbounds(dbInbounds) {
|
setInbounds(dbInbounds) {
|
||||||
|
|
|
@ -138,6 +138,27 @@
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
|
||||||
|
<a-list-item>
|
||||||
|
<a-row style="padding: 20px">
|
||||||
|
<a-col :lg="24" :xl="12">
|
||||||
|
<a-list-item-meta title='{{ i18n "pages.settings.datepicker"}}'>
|
||||||
|
<template slot="description">{{ i18n "pages.settings.datepickerDescription"}}</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :lg="24" :xl="12">
|
||||||
|
<template>
|
||||||
|
<a-select style="width: 100%"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
|
v-model="datepicker">
|
||||||
|
<a-select-option v-for="item in datepickerList" :value="item.value">
|
||||||
|
<span v-text="item.name"></span>
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-list-item>
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
<a-row style="padding: 20px">
|
<a-row style="padding: 20px">
|
||||||
<a-col :lg="24" :xl="12">
|
<a-col :lg="24" :xl="12">
|
||||||
|
@ -197,7 +218,7 @@
|
||||||
<td>
|
<td>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<password-input v-model="user.newPassword" style="width: 200px"></password-input>
|
<password-input v-model="user.newPassword" style="width: 200px"></password-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -311,6 +332,7 @@
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
remarkModels: {i:'Inbound',e:'Email',o:'Other'},
|
remarkModels: {i:'Inbound',e:'Email',o:'Other'},
|
||||||
remarkSeparators: [' ','-','_','@',':','~','|',',','.','/'],
|
remarkSeparators: [' ','-','_','@',':','~','|',',','.','/'],
|
||||||
|
datepickerList: [{name:'Gregorian (Standard)', value: 'gregorian'}, {name:'Jalalian (شمسی)', value: 'jalalian'}],
|
||||||
remarkSample: '',
|
remarkSample: '',
|
||||||
get remarkModel() {
|
get remarkModel() {
|
||||||
rm = this.allSetting.remarkModel;
|
rm = this.allSetting.remarkModel;
|
||||||
|
@ -328,11 +350,17 @@
|
||||||
this.allSetting.remarkModel = value + this.allSetting.remarkModel.substring(1);
|
this.allSetting.remarkModel = value + this.allSetting.remarkModel.substring(1);
|
||||||
this.changeRemarkSample();
|
this.changeRemarkSample();
|
||||||
},
|
},
|
||||||
|
get datepicker() {
|
||||||
|
return this.allSetting.datepicker ? this.allSetting.datepicker : 'gregorian';
|
||||||
|
},
|
||||||
|
set datepicker(value) {
|
||||||
|
this.allSetting.datepicker = value;
|
||||||
|
},
|
||||||
changeRemarkSample(){
|
changeRemarkSample(){
|
||||||
sample = []
|
sample = []
|
||||||
this.remarkModel.forEach(r => sample.push(this.remarkModels[r]));
|
this.remarkModel.forEach(r => sample.push(this.remarkModels[r]));
|
||||||
this.remarkSample = sample.length == 0 ? '' : sample.join(this.remarkSeparator);
|
this.remarkSample = sample.length == 0 ? '' : sample.join(this.remarkSeparator);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning = true) {
|
loading(spinning = true) {
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">{{ i18n "pages.xray.save" }}</a-button>
|
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">{{ i18n "pages.xray.save" }}</a-button>
|
||||||
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">{{ i18n "pages.xray.restart" }}</a-button>
|
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">{{ i18n "pages.xray.restart" }}</a-button>
|
||||||
<a-popover v-if="restartResult"
|
<a-popover v-if="restartResult"
|
||||||
:overlay-class-name="themeSwitcher.currentTheme">
|
:overlay-class-name="themeSwitcher.currentTheme">
|
||||||
<span slot="title" style="font-size: 12pt">Error in running xray-core</span>
|
<span slot="title" style="font-size: 12pt">Error in running xray-core</span>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<p style="max-width: 400px" v-for="line in restartResult.split('\n')">[[ line ]]</p>
|
<p style="max-width: 400px" v-for="line in restartResult.split('\n')">[[ line ]]</p>
|
||||||
|
@ -83,15 +83,15 @@
|
||||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200">
|
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200">
|
||||||
</a-back-top>
|
</a-back-top>
|
||||||
<a-alert type="warning" style="float: right; width: fit-content"
|
<a-alert type="warning" style="float: right; width: fit-content"
|
||||||
message='{{ i18n "pages.settings.infoDesc" }}'
|
message='{{ i18n "pages.settings.infoDesc" }}'
|
||||||
show-icon
|
show-icon
|
||||||
>
|
>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
<a-tabs class="ant-card-dark-box-nohover" default-active-key="tpl-1"
|
<a-tabs class="ant-card-dark-box-nohover" default-active-key="tpl-1"
|
||||||
@change="(activeKey) => { if(activeKey == 'tpl-4') this.changeCode(); }"
|
@change="(activeKey) => { if(activeKey == 'tpl-4') this.changeCode(); }"
|
||||||
:class="themeSwitcher.currentTheme">
|
:class="themeSwitcher.currentTheme">
|
||||||
<a-tab-pane key="tpl-1" tab='{{ i18n "pages.xray.basicTemplate"}}'>
|
<a-tab-pane key="tpl-1" tab='{{ i18n "pages.xray.basicTemplate"}}'>
|
||||||
<a-space direction="horizontal" style="padding: 20px 20px">
|
<a-space direction="horizontal" style="padding: 20px 20px">
|
||||||
<a-button type="primary" @click="resetXrayConfigToDefault">{{ i18n "pages.settings.resetDefaultConfig" }}</a-button>
|
<a-button type="primary" @click="resetXrayConfigToDefault">{{ i18n "pages.settings.resetDefaultConfig" }}</a-button>
|
||||||
|
@ -109,16 +109,16 @@
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
<a-row style="padding: 20px">
|
<a-row style="padding: 20px">
|
||||||
<a-col :lg="24" :xl="12">
|
<a-col :lg="24" :xl="12">
|
||||||
<a-list-item-meta
|
<a-list-item-meta
|
||||||
title='{{ i18n "pages.xray.FreedomStrategy" }}'
|
title='{{ i18n "pages.xray.FreedomStrategy" }}'
|
||||||
description='{{ i18n "pages.xray.FreedomStrategyDesc" }}'/>
|
description='{{ i18n "pages.xray.FreedomStrategyDesc" }}'/>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="24" :xl="12">
|
<a-col :lg="24" :xl="12">
|
||||||
<template>
|
<template>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="freedomStrategy"
|
v-model="freedomStrategy"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<a-select-option v-for="s in outboundDomainStrategies" :value="s">[[ s ]]</a-select-option>
|
<a-select-option v-for="s in outboundDomainStrategies" :value="s">[[ s ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</template>
|
</template>
|
||||||
|
@ -127,22 +127,22 @@
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
<a-row style="padding: 20px">
|
<a-row style="padding: 20px">
|
||||||
<a-col :lg="24" :xl="12">
|
<a-col :lg="24" :xl="12">
|
||||||
<a-list-item-meta
|
<a-list-item-meta
|
||||||
title='{{ i18n "pages.xray.RoutingStrategy" }}'
|
title='{{ i18n "pages.xray.RoutingStrategy" }}'
|
||||||
description='{{ i18n "pages.xray.RoutingStrategyDesc" }}'/>
|
description='{{ i18n "pages.xray.RoutingStrategyDesc" }}'/>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="24" :xl="12">
|
<a-col :lg="24" :xl="12">
|
||||||
<template>
|
<template>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="routingStrategy"
|
v-model="routingStrategy"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<a-select-option v-for="s in routingDomainStrategies" :value="s">[[ s ]]</a-select-option>
|
<a-select-option v-for="s in routingDomainStrategies" :value="s">[[ s ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</template>
|
</template>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel header='{{ i18n "pages.xray.blockConfigs"}}'>
|
<a-collapse-panel header='{{ i18n "pages.xray.blockConfigs"}}'>
|
||||||
<a-row :xs="24" :sm="24" :lg="12">
|
<a-row :xs="24" :sm="24" :lg="12">
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.ChinaDomain"}}' desc='{{ i18n "pages.xray.ChinaDomainDesc"}}' v-model="ChinaDomainSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.ChinaDomain"}}' desc='{{ i18n "pages.xray.ChinaDomainDesc"}}' v-model="ChinaDomainSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaIp"}}' desc='{{ i18n "pages.xray.RussiaIpDesc"}}' v-model="RussiaIpSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaIp"}}' desc='{{ i18n "pages.xray.RussiaIpDesc"}}' v-model="RussiaIpSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaDomain"}}' desc='{{ i18n "pages.xray.RussiaDomainDesc"}}' v-model="RussiaDomainSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaDomain"}}' desc='{{ i18n "pages.xray.RussiaDomainDesc"}}' v-model="RussiaDomainSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.VNIp"}}' desc='{{ i18n "pages.xray.VNIpDesc"}}' v-model="VNIpSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.VNIp"}}' desc='{{ i18n "pages.xray.VNIpDesc"}}' v-model="VNIpSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.VNDomain"}}' desc='{{ i18n "pages.xray.VNDomainDesc"}}' v-model="VNDomainSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.VNDomain"}}' desc='{{ i18n "pages.xray.VNDomainDesc"}}' v-model="VNDomainSettings"></setting-list-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel header='{{ i18n "pages.xray.directCountryConfigs"}}'>
|
<a-collapse-panel header='{{ i18n "pages.xray.directCountryConfigs"}}'>
|
||||||
|
@ -193,8 +193,8 @@
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectChinaDomain"}}' desc='{{ i18n "pages.xray.DirectChinaDomainDesc"}}' v-model="ChinaDomainDirectSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectChinaDomain"}}' desc='{{ i18n "pages.xray.DirectChinaDomainDesc"}}' v-model="ChinaDomainDirectSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaIp"}}' desc='{{ i18n "pages.xray.DirectRussiaIpDesc"}}' v-model="RussiaIpDirectSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaIp"}}' desc='{{ i18n "pages.xray.DirectRussiaIpDesc"}}' v-model="RussiaIpDirectSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaDomain"}}' desc='{{ i18n "pages.xray.DirectRussiaDomainDesc"}}' v-model="RussiaDomainDirectSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaDomain"}}' desc='{{ i18n "pages.xray.DirectRussiaDomainDesc"}}' v-model="RussiaDomainDirectSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNIp"}}' desc='{{ i18n "pages.xray.DirectVNIpDesc"}}' v-model="VNIpDirectSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNIp"}}' desc='{{ i18n "pages.xray.DirectVNIpDesc"}}' v-model="VNIpDirectSettings"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNDomain"}}' desc='{{ i18n "pages.xray.DirectVNDomainDesc"}}' v-model="VNDomainDirectSettings"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNDomain"}}' desc='{{ i18n "pages.xray.DirectVNDomainDesc"}}' v-model="VNDomainDirectSettings"></setting-list-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel header='{{ i18n "pages.xray.ipv4Configs"}}'>
|
<a-collapse-panel header='{{ i18n "pages.xray.ipv4Configs"}}'>
|
||||||
<a-row :xs="24" :sm="24" :lg="12">
|
<a-row :xs="24" :sm="24" :lg="12">
|
||||||
|
@ -226,15 +226,15 @@
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="tpl-2" tab='{{ i18n "pages.xray.Routings"}}' style="padding-top: 20px;">
|
<a-tab-pane key="tpl-2" tab='{{ i18n "pages.xray.Routings"}}' style="padding-top: 20px;">
|
||||||
<a-alert type="warning" style="margin-bottom: 10px; width: fit-content"
|
<a-alert type="warning" style="margin-bottom: 10px; width: fit-content"
|
||||||
message='{{ i18n "pages.xray.RoutingsDesc"}}' show-icon></a-alert>
|
message='{{ i18n "pages.xray.RoutingsDesc"}}' show-icon></a-alert>
|
||||||
<a-button type="primary" icon="plus" @click="addRule">{{ i18n "pages.xray.rules.add" }}</a-button>
|
<a-button type="primary" icon="plus" @click="addRule">{{ i18n "pages.xray.rules.add" }}</a-button>
|
||||||
<a-table :columns="isMobile ? rulesMobileColumns : rulesColumns" bordered
|
<a-table :columns="isMobile ? rulesMobileColumns : rulesColumns" bordered
|
||||||
:row-key="r => r.key"
|
:row-key="r => r.key"
|
||||||
:data-source="routingRuleData"
|
:data-source="routingRuleData"
|
||||||
:scroll="isMobile ? {} : { x: 1000 }"
|
:scroll="isMobile ? {} : { x: 1000 }"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:indent-size="0"
|
:indent-size="0"
|
||||||
:style="isMobile ? 'padding: 5px 0' : 'margin-top: 10px;'">
|
:style="isMobile ? 'padding: 5px 0' : 'margin-top: 10px;'">
|
||||||
<template slot="action" slot-scope="text, rule, index">
|
<template slot="action" slot-scope="text, rule, index">
|
||||||
[[ index+1 ]]
|
[[ index+1 ]]
|
||||||
<a-dropdown :trigger="['click']">
|
<a-dropdown :trigger="['click']">
|
||||||
|
@ -287,8 +287,8 @@
|
||||||
</template>
|
</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"
|
||||||
:overlay-class-name="themeSwitcher.currentTheme" trigger="click">
|
:overlay-class-name="themeSwitcher.currentTheme" trigger="click">
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<table cellpadding="2" style="max-width: 300px;">
|
<table cellpadding="2" style="max-width: 300px;">
|
||||||
<tr v-if="rule.source">
|
<tr v-if="rule.source">
|
||||||
|
@ -339,12 +339,12 @@
|
||||||
<a-col :sm="24" :md="12">
|
<a-col :sm="24" :md="12">
|
||||||
<p style="margin: 10px;">{{ i18n "pages.xray.Outbounds"}}</p>
|
<p style="margin: 10px;">{{ i18n "pages.xray.Outbounds"}}</p>
|
||||||
<a-table :columns="outboundColumns" bordered
|
<a-table :columns="outboundColumns" bordered
|
||||||
:row-key="r => r.key"
|
:row-key="r => r.key"
|
||||||
:data-source="outboundData"
|
:data-source="outboundData"
|
||||||
:scroll="isMobile ? {} : { x: 200 }"
|
:scroll="isMobile ? {} : { x: 200 }"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:indent-size="0"
|
:indent-size="0"
|
||||||
:style="isMobile ? 'padding: 5px 5px' : 'margin-right: 1px;'">
|
:style="isMobile ? 'padding: 5px 5px' : 'margin-right: 1px;'">
|
||||||
<template slot="action" slot-scope="text, outbound, index">
|
<template slot="action" slot-scope="text, outbound, index">
|
||||||
[[ index+1 ]]
|
[[ index+1 ]]
|
||||||
<a-dropdown :trigger="['click']">
|
<a-dropdown :trigger="['click']">
|
||||||
|
@ -378,12 +378,12 @@
|
||||||
<a-col :sm="24" :md="12" v-if="reverseData.length>0">
|
<a-col :sm="24" :md="12" v-if="reverseData.length>0">
|
||||||
<p style="margin: 10px;">{{ i18n "pages.xray.outbound.reverse"}}</p>
|
<p style="margin: 10px;">{{ i18n "pages.xray.outbound.reverse"}}</p>
|
||||||
<a-table :columns="reverseColumns" bordered
|
<a-table :columns="reverseColumns" bordered
|
||||||
:row-key="r => r.key"
|
:row-key="r => r.key"
|
||||||
:data-source="reverseData"
|
:data-source="reverseData"
|
||||||
:scroll="isMobile ? {} : { x: 200 }"
|
:scroll="isMobile ? {} : { x: 200 }"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:indent-size="0"
|
:indent-size="0"
|
||||||
:style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'">
|
:style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'">
|
||||||
<template slot="action" slot-scope="text, reverse, index">
|
<template slot="action" slot-scope="text, reverse, index">
|
||||||
[[ index+1 ]]
|
[[ index+1 ]]
|
||||||
<a-dropdown :trigger="['click']">
|
<a-dropdown :trigger="['click']">
|
||||||
|
@ -428,22 +428,22 @@
|
||||||
{{template "outModal"}}
|
{{template "outModal"}}
|
||||||
{{template "reverseModal"}}
|
{{template "reverseModal"}}
|
||||||
<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: 'port', dataIndex: 'sourcePort', align: 'center', width: 10, ellipsis: true } ]},
|
{ title: '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: 'Protocol', dataIndex: 'protocol', align: 'center', width: 10, ellipsis: true },
|
{ title: 'Protocol', dataIndex: 'protocol', align: 'center', width: 10, ellipsis: true },
|
||||||
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 20, ellipsis: true } ]},
|
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 20, 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: '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: 20, 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: 20 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@
|
||||||
cn: ["geoip:cn"],
|
cn: ["geoip:cn"],
|
||||||
ir: ["ext:geoip_IR.dat:ir"],
|
ir: ["ext:geoip_IR.dat:ir"],
|
||||||
ru: ["geoip:ru"],
|
ru: ["geoip:ru"],
|
||||||
vn: ["ext:geoip_VN.dat:vn"],
|
vn: ["ext:geoip_VN.dat:vn"],
|
||||||
},
|
},
|
||||||
domains: {
|
domains: {
|
||||||
ads: [
|
ads: [
|
||||||
|
@ -568,11 +568,11 @@
|
||||||
"regexp:.*\\.xn--mgba3a4f16a$", // .ایران
|
"regexp:.*\\.xn--mgba3a4f16a$", // .ایران
|
||||||
"ext:geosite_IR.dat:ir"
|
"ext:geosite_IR.dat:ir"
|
||||||
],
|
],
|
||||||
vn: [
|
vn: [
|
||||||
"regexp:.*\\.vn$",
|
"regexp:.*\\.vn$",
|
||||||
"ext:geosite_VN.dat:vn",
|
"ext:geosite_VN.dat:vn",
|
||||||
"ext:geosite_VN.dat:ads"
|
"ext:geosite_VN.dat:ads"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
familyProtectDNS: {
|
familyProtectDNS: {
|
||||||
"servers": [
|
"servers": [
|
||||||
|
@ -620,10 +620,10 @@
|
||||||
},
|
},
|
||||||
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 fetchUserSecret() {
|
async fetchUserSecret() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
|
@ -661,9 +661,9 @@
|
||||||
},
|
},
|
||||||
async toggleToken(value) {
|
async toggleToken(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
await this.getNewSecret();
|
await this.getNewSecret();
|
||||||
} else {
|
} else {
|
||||||
this.user.loginSecret = "";
|
this.user.loginSecret = "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async resetXrayConfigToDefault() {
|
async resetXrayConfigToDefault() {
|
||||||
|
@ -902,7 +902,7 @@
|
||||||
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;
|
||||||
|
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
},
|
},
|
||||||
addRule(){
|
addRule(){
|
||||||
|
@ -1321,7 +1321,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
VNIpSettings: {
|
VNIpSettings: {
|
||||||
get: function () {
|
get: function () {
|
||||||
return doAllItemsExist(this.settingsData.ips.vn, this.blockedIPs);
|
return doAllItemsExist(this.settingsData.ips.vn, this.blockedIPs);
|
||||||
},
|
},
|
||||||
|
@ -1417,7 +1417,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
VNIpDirectSettings: {
|
VNIpDirectSettings: {
|
||||||
get: function () {
|
get: function () {
|
||||||
return doAllItemsExist(this.settingsData.ips.vn, this.directIPs);
|
return doAllItemsExist(this.settingsData.ips.vn, this.directIPs);
|
||||||
},
|
},
|
||||||
|
@ -1440,7 +1440,7 @@
|
||||||
this.directDomains = this.directDomains.filter(data => !this.settingsData.domains.vn.includes(data));
|
this.directDomains = this.directDomains.filter(data => !this.settingsData.domains.vn.includes(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GoogleWARPSettings: {
|
GoogleWARPSettings: {
|
||||||
get: function () {
|
get: function () {
|
||||||
return doAllItemsExist(this.settingsData.domains.google, this.warpDomains);
|
return doAllItemsExist(this.settingsData.domains.google, this.warpDomains);
|
||||||
|
@ -1493,4 +1493,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -4,9 +4,9 @@
|
||||||
:ok-text="ruleModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
|
:ok-text="ruleModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
|
||||||
<a-form :colon="false" :label-col="{ md: {span:6} }" :wrapper-col="{ md: {span:14} }">
|
<a-form :colon="false" :label-col="{ md: {span:6} }" :wrapper-col="{ md: {span:14} }">
|
||||||
<a-form-item label='Domain Matcher'>
|
<a-form-item label='Domain Matcher'>
|
||||||
<a-select v-model="ruleModal.rule.domainMatcher" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select v-model="ruleModal.rule.domainMatcher" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option v-for="dm in ['','hybrid','linear']" :value="dm">[[ dm ]]</a-select-option>
|
<a-select-option v-for="dm in ['','hybrid','linear']" :value="dm">[[ dm ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
<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>
|
||||||
</table>
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<script>
|
<script>
|
||||||
|
@ -214,11 +214,11 @@
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(rule)) {
|
for (const [key, value] of Object.entries(rule)) {
|
||||||
if (
|
if (
|
||||||
value !== null &&
|
value !== null &&
|
||||||
value !== undefined &&
|
value !== undefined &&
|
||||||
!(Array.isArray(value) && value.length === 0) &&
|
!(Array.isArray(value) && value.length === 0) &&
|
||||||
!(typeof value === 'object' && Object.keys(value).length === 0) &&
|
!(typeof value === 'object' && Object.keys(value).length === 0) &&
|
||||||
value !== ''
|
value !== ''
|
||||||
) {
|
) {
|
||||||
newRule[key] = value;
|
newRule[key] = value;
|
||||||
}
|
}
|
||||||
|
@ -236,4 +236,4 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
|
@ -56,6 +56,7 @@ var defaultValueMap = map[string]string{
|
||||||
"subEncrypt": "true",
|
"subEncrypt": "true",
|
||||||
"subShowInfo": "true",
|
"subShowInfo": "true",
|
||||||
"subURI": "",
|
"subURI": "",
|
||||||
|
"datepicker": "gregorian",
|
||||||
}
|
}
|
||||||
|
|
||||||
type SettingService struct {
|
type SettingService struct {
|
||||||
|
@ -417,6 +418,10 @@ func (s *SettingService) GetSubURI() (string, error) {
|
||||||
return s.getString("subURI")
|
return s.getString("subURI")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SettingService) GetDatepicker() (string, error) {
|
||||||
|
return s.getString("datepicker")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SettingService) GetPageSize() (int, error) {
|
func (s *SettingService) GetPageSize() (int, error) {
|
||||||
return s.getInt("pageSize")
|
return s.getInt("pageSize")
|
||||||
}
|
}
|
||||||
|
@ -463,6 +468,7 @@ func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) {
|
||||||
"subEnable": func() (interface{}, error) { return s.GetSubEnable() },
|
"subEnable": func() (interface{}, error) { return s.GetSubEnable() },
|
||||||
"subURI": func() (interface{}, error) { return s.GetSubURI() },
|
"subURI": func() (interface{}, error) { return s.GetSubURI() },
|
||||||
"remarkModel": func() (interface{}, error) { return s.GetRemarkModel() },
|
"remarkModel": func() (interface{}, error) { return s.GetRemarkModel() },
|
||||||
|
"datepicker": func() (interface{}, error) { return s.GetDatepicker() },
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]interface{})
|
||||||
|
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "Pagination Size"
|
"pageSize" = "Pagination Size"
|
||||||
"pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable"
|
"pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable"
|
||||||
"remarkModel" = "Remark Model and Seperation Charachter"
|
"remarkModel" = "Remark Model and Seperation Charachter"
|
||||||
|
"datepicker" = "Datepicker"
|
||||||
|
"datepickerDescription" = "Selector calendar type specifies the expiration date"
|
||||||
"sampleRemark" = "Sample Remark"
|
"sampleRemark" = "Sample Remark"
|
||||||
"oldUsername" = "Current Username"
|
"oldUsername" = "Current Username"
|
||||||
"currentPassword" = "Current Password"
|
"currentPassword" = "Current Password"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }} : Enabled successfully."
|
"enableSuccess" = "✅ {{ .Email }} : Enabled successfully."
|
||||||
"disableSuccess" = "✅ {{ .Email }} : Disabled successfully."
|
"disableSuccess" = "✅ {{ .Email }} : Disabled successfully."
|
||||||
"askToAddUserId" = "Your configuration is not found!\r\nPlease ask your Admin to use your telegram user id in your configuration(s).\r\n\r\nYour user id: <b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "Your configuration is not found!\r\nPlease ask your Admin to use your telegram user id in your configuration(s).\r\n\r\nYour user id: <b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "Your configuration is not found!\r\nPlease ask your Admin to use your telegram username or user id in your configuration(s).\r\n\r\nYour username: <b>@{{ .TgUserName }}</b>\r\n\r\nYour user id: <b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "Your configuration is not found!\r\nPlease ask your Admin to use your telegram username or user id in your configuration(s).\r\n\r\nYour username: <b>@{{ .TgUserName }}</b>\r\n\r\nYour user id: <b>{{ .TgUserID }}</b>"
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "Tamaño de paginación"
|
"pageSize" = "Tamaño de paginación"
|
||||||
"pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar"
|
"pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar"
|
||||||
"remarkModel" = "Modelo de observación y carácter de separación"
|
"remarkModel" = "Modelo de observación y carácter de separación"
|
||||||
|
"datepicker" = "selector de fechas"
|
||||||
|
"datepickerDescription" = "El tipo de calendario selector especifica la fecha de vencimiento"
|
||||||
"sampleRemark" = "Observación de muestra"
|
"sampleRemark" = "Observación de muestra"
|
||||||
"oldUsername" = "Nombre de Usuario Actual"
|
"oldUsername" = "Nombre de Usuario Actual"
|
||||||
"currentPassword" = "Contraseña Actual"
|
"currentPassword" = "Contraseña Actual"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }} : Habilitado exitosamente."
|
"enableSuccess" = "✅ {{ .Email }} : Habilitado exitosamente."
|
||||||
"disableSuccess" = "✅ {{ .Email }} : Deshabilitado exitosamente."
|
"disableSuccess" = "✅ {{ .Email }} : Deshabilitado exitosamente."
|
||||||
"askToAddUserId" = "¡No se encuentra su configuración!\r\nPor favor, pídale a su administrador que use su ID de usuario de Telegram en su(s) configuración(es).\r\n\r\nSu ID de usuario: <b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "¡No se encuentra su configuración!\r\nPor favor, pídale a su administrador que use su ID de usuario de Telegram en su(s) configuración(es).\r\n\r\nSu ID de usuario: <b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "¡No se encuentra su configuración!\r\nPor favor, pídale a su administrador que use su nombre de usuario o ID de usuario de Telegram en su(s) configuración(es).\r\n\r\nSu nombre de usuario: <b>@{{ .TgUserName }}</b>\r\n\r\nSu ID de usuario: <b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "¡No se encuentra su configuración!\r\nPor favor, pídale a su administrador que use su nombre de usuario o ID de usuario de Telegram en su(s) configuración(es).\r\n\r\nSu nombre de usuario: <b>@{{ .TgUserName }}</b>\r\n\r\nSu ID de usuario: <b>{{ .TgUserID }}</b>"
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "اندازه صفحه بندی جدول"
|
"pageSize" = "اندازه صفحه بندی جدول"
|
||||||
"pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال"
|
"pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال"
|
||||||
"remarkModel" = "نام کانفیگ و جداکننده"
|
"remarkModel" = "نام کانفیگ و جداکننده"
|
||||||
|
"datepicker" = "انتخاب کننده تاریخ"
|
||||||
|
"datepickerDescription" = "نوع تقویم انتخاب کننده تاریخ انقضا را مشخص میکند "
|
||||||
"sampleRemark" = "نمونه نام"
|
"sampleRemark" = "نمونه نام"
|
||||||
"oldUsername" = "نام کاربری فعلی"
|
"oldUsername" = "نام کاربری فعلی"
|
||||||
"currentPassword" = "رمز عبور فعلی"
|
"currentPassword" = "رمز عبور فعلی"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }} : با موفقیت فعال شد."
|
"enableSuccess" = "✅ {{ .Email }} : با موفقیت فعال شد."
|
||||||
"disableSuccess" = "✅ {{ .Email }} : با موفقیت غیرفعال شد."
|
"disableSuccess" = "✅ {{ .Email }} : با موفقیت غیرفعال شد."
|
||||||
"askToAddUserId" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر خود بخواهید که شناسه کاربر تلگرام خود را در پیکربندی (های) خود استفاده کند.\r\n\r\nشناسه کاربری شما: <b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر خود بخواهید که شناسه کاربر تلگرام خود را در پیکربندی (های) خود استفاده کند.\r\n\r\nشناسه کاربری شما: <b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر خود بخواهید که نام کاربری یا شناسه کاربر تلگرام خود را در پیکربندی (های) خود استفاده کند.\r\n\r\nنام کاربری شما: <b>@{{ .TgUserName }}</b>\r\n\r\nشناسه کاربری شما: <b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر خود بخواهید که نام کاربری یا شناسه کاربر تلگرام خود را در پیکربندی (های) خود استفاده کند.\r\n\r\nنام کاربری شما: <b>@{{ .TgUserName }}</b>\r\n\r\nشناسه کاربری شما: <b>{{ .TgUserID }}</b>"
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "Размер нумерации страниц"
|
"pageSize" = "Размер нумерации страниц"
|
||||||
"pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить"
|
"pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить"
|
||||||
"remarkModel" = "Модель примечания и символ разделения"
|
"remarkModel" = "Модель примечания и символ разделения"
|
||||||
|
"datepicker" = "выбор даты"
|
||||||
|
"datepickerDescription" = "Тип календаря выбора указывает дату истечения срока действия."
|
||||||
"sampleRemark" = "Пример замечания"
|
"sampleRemark" = "Пример замечания"
|
||||||
"oldUsername" = "Текущее имя пользователя"
|
"oldUsername" = "Текущее имя пользователя"
|
||||||
"currentPassword" = "Текущий пароль"
|
"currentPassword" = "Текущий пароль"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
|
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
|
||||||
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
|
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
|
||||||
"askToAddUserId" = "Ваша конфигурация не найдена!\r\nПожалуйста, попросите администратора использовать ваш идентификатор пользователя Telegram в ваших конфигурациях.\r\n\r\nВаш идентификатор пользователя: <b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "Ваша конфигурация не найдена!\r\nПожалуйста, попросите администратора использовать ваш идентификатор пользователя Telegram в ваших конфигурациях.\r\n\r\nВаш идентификатор пользователя: <b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "Ваша конфигурация не найдена!\r\nПожалуйста, попросите администратора использовать ваше имя пользователя или идентификатор пользователя Telegram в ваших конфигурациях.\r\n\r\nВаше имя пользователя: <b>@{{ .TgUserName }}</b>\r\n\r\nВаш идентификатор пользователя: <b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "Ваша конфигурация не найдена!\r\nПожалуйста, попросите администратора использовать ваше имя пользователя или идентификатор пользователя Telegram в ваших конфигурациях.\r\n\r\nВаше имя пользователя: <b>@{{ .TgUserName }}</b>\r\n\r\nВаш идентификатор пользователя: <b>{{ .TgUserID }}</b>"
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "Kích thước phân trang"
|
"pageSize" = "Kích thước phân trang"
|
||||||
"pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt"
|
"pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt"
|
||||||
"remarkModel" = "Ghi chú mô hình và ký tự phân tách"
|
"remarkModel" = "Ghi chú mô hình và ký tự phân tách"
|
||||||
|
"datepicker" = "bảng chọn ngày"
|
||||||
|
"datepickerDescription" = "Loại lịch chọn chỉ định ngày hết hạn"
|
||||||
"sampleRemark" = "Nhận xét mẫu"
|
"sampleRemark" = "Nhận xét mẫu"
|
||||||
"oldUsername" = "Tên người dùng hiện tại"
|
"oldUsername" = "Tên người dùng hiện tại"
|
||||||
"currentPassword" = "Mật khẩu hiện tại"
|
"currentPassword" = "Mật khẩu hiện tại"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }} : Đã Bật Thành Công."
|
"enableSuccess" = "✅ {{ .Email }} : Đã Bật Thành Công."
|
||||||
"disableSuccess" = "✅ {{ .Email }} : Đã Tắt Thành Công."
|
"disableSuccess" = "✅ {{ .Email }} : Đã Tắt Thành Công."
|
||||||
"askToAddUserId" = "Cấu hình của bạn không được tìm thấy!\r\nVui lòng yêu cầu Quản trị viên sử dụng ID người dùng telegram của bạn trong cấu hình của bạn.\r\n\r\nID người dùng của bạn: <b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "Cấu hình của bạn không được tìm thấy!\r\nVui lòng yêu cầu Quản trị viên sử dụng ID người dùng telegram của bạn trong cấu hình của bạn.\r\n\r\nID người dùng của bạn: <b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "Cấu hình của bạn không được tìm thấy!\r\nVui lòng yêu cầu Quản trị viên sử dụng tên người dùng hoặc ID người dùng telegram của bạn trong cấu hình của bạn.\r\n\r\nTên người dùng của bạn: <b>@{{ .TgUserName }}</b>\r\n\r\nID người dùng của bạn: <b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "Cấu hình của bạn không được tìm thấy!\r\nVui lòng yêu cầu Quản trị viên sử dụng tên người dùng hoặc ID người dùng telegram của bạn trong cấu hình của bạn.\r\n\r\nTên người dùng của bạn: <b>@{{ .TgUserName }}</b>\r\n\r\nID người dùng của bạn: <b>{{ .TgUserID }}</b>"
|
|
@ -246,6 +246,8 @@
|
||||||
"pageSize" = "分页大小"
|
"pageSize" = "分页大小"
|
||||||
"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
|
"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
|
||||||
"remarkModel" = "备注模型和分隔符"
|
"remarkModel" = "备注模型和分隔符"
|
||||||
|
"datepicker" = "日期选择器"
|
||||||
|
"datepickerDescription" = "选择器日历类型指定到期日期"
|
||||||
"sampleRemark" = "备注示例"
|
"sampleRemark" = "备注示例"
|
||||||
"oldUsername" = "原用户名"
|
"oldUsername" = "原用户名"
|
||||||
"currentPassword" = "原密码"
|
"currentPassword" = "原密码"
|
||||||
|
@ -422,7 +424,7 @@
|
||||||
"loginSecurity" = "登录安全"
|
"loginSecurity" = "登录安全"
|
||||||
"loginSecurityDesc" = "在用户登录页面中切换附加步骤"
|
"loginSecurityDesc" = "在用户登录页面中切换附加步骤"
|
||||||
"secretToken" = "密钥"
|
"secretToken" = "密钥"
|
||||||
"secretTokenDesc" = "复制此密钥并将其保存在安全的地方;没有这个你将无法登录。这也无法从 x-ui 命令工具中恢复"
|
"secretTokenDesc" = "复制此密钥并将其保存在安全的地方;没有这个你将无法登录。这也无法从 x-ui 命令工具中恢复"
|
||||||
|
|
||||||
[pages.settings.toasts]
|
[pages.settings.toasts]
|
||||||
"modifySettings" = "修改设置"
|
"modifySettings" = "修改设置"
|
||||||
|
@ -549,4 +551,4 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }}:已成功启用。"
|
"enableSuccess" = "✅ {{ .Email }}:已成功启用。"
|
||||||
"disableSuccess" = "✅ {{ .Email }}:已成功禁用。"
|
"disableSuccess" = "✅ {{ .Email }}:已成功禁用。"
|
||||||
"askToAddUserId" = "未找到您的配置!\r\n请向管理员询问,在您的配置中使用您的 Telegram 用户ID。\r\n\r\n您的用户ID:<b>{{ .TgUserID }}</b>"
|
"askToAddUserId" = "未找到您的配置!\r\n请向管理员询问,在您的配置中使用您的 Telegram 用户ID。\r\n\r\n您的用户ID:<b>{{ .TgUserID }}</b>"
|
||||||
"askToAddUserName" = "未找到您的配置!\r\n请向管理员询问,在您的配置中使用您的 Telegram 用户名或用户ID。\r\n\r\n您的用户名:<b>@{{ .TgUserName }}</b>\r\n\r\n您的用户ID:<b>{{ .TgUserID }}</b>"
|
"askToAddUserName" = "未找到您的配置!\r\n请向管理员询问,在您的配置中使用您的 Telegram 用户名或用户ID。\r\n\r\n您的用户名:<b>@{{ .TgUserName }}</b>\r\n\r\n您的用户ID:<b>{{ .TgUserID }}</b>"
|
118
x-ui.sh
118
x-ui.sh
|
@ -54,10 +54,6 @@ elif [[ "${release}" == "debian" ]]; then
|
||||||
if [[ ${os_version} -lt 10 ]]; then
|
if [[ ${os_version} -lt 10 ]]; then
|
||||||
echo -e "${red} Please use Debian 10 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use Debian 10 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "almalinux" ]]; then
|
|
||||||
if [[ ${os_version} -lt 9 ]]; then
|
|
||||||
echo -e "${red} Please use Almalinux 9 or higher ${plain}\n" && exit 1
|
|
||||||
fi
|
|
||||||
elif [[ "${release}" == "arch" ]]; then
|
elif [[ "${release}" == "arch" ]]; then
|
||||||
echo "Your OS is ArchLinux"
|
echo "Your OS is ArchLinux"
|
||||||
elif [[ "${release}" == "manjaro" ]]; then
|
elif [[ "${release}" == "manjaro" ]]; then
|
||||||
|
@ -104,7 +100,7 @@ before_show_menu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/alirahimi818/3x-ui/main/install.sh)
|
||||||
if [[ $? == 0 ]]; then
|
if [[ $? == 0 ]]; then
|
||||||
if [[ $# == 0 ]]; then
|
if [[ $# == 0 ]]; then
|
||||||
start
|
start
|
||||||
|
@ -123,31 +119,13 @@ update() {
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/alirahimi818/3x-ui/main/install.sh)
|
||||||
if [[ $? == 0 ]]; then
|
if [[ $? == 0 ]]; then
|
||||||
LOGI "Update is complete, Panel has automatically restarted "
|
LOGI "Update is complete, Panel has automatically restarted "
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_version() {
|
|
||||||
echo "Enter the panel version (like 2.0.0):"
|
|
||||||
read panel_version
|
|
||||||
|
|
||||||
if [ -z "$panel_version" ]; then
|
|
||||||
echo "Panel version cannot be empty. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
download_link="https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh"
|
|
||||||
|
|
||||||
# Use the entered panel version in the download link
|
|
||||||
install_command="bash <(curl -Ls $download_link) v$panel_version"
|
|
||||||
|
|
||||||
echo "Downloading and installing panel version $panel_version..."
|
|
||||||
eval $install_command
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
confirm "Are you sure you want to uninstall the panel? xray will also uninstalled!" "n"
|
confirm "Are you sure you want to uninstall the panel? xray will also uninstalled!" "n"
|
||||||
if [[ $? != 0 ]]; then
|
if [[ $? != 0 ]]; then
|
||||||
|
@ -375,7 +353,7 @@ enable_bbr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
update_shell() {
|
update_shell() {
|
||||||
wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/MHSanaei/3x-ui/raw/main/x-ui.sh
|
wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/alirahimi818/3x-ui/raw/main/x-ui.sh
|
||||||
if [[ $? != 0 ]]; then
|
if [[ $? != 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
LOGE "Failed to download script, Please check whether the machine can connect Github"
|
LOGE "Failed to download script, Please check whether the machine can connect Github"
|
||||||
|
@ -1057,37 +1035,36 @@ show_menu() {
|
||||||
${green}3X-ui Panel Management Script${plain}
|
${green}3X-ui Panel Management Script${plain}
|
||||||
${green}0.${plain} Exit Script
|
${green}0.${plain} Exit Script
|
||||||
————————————————
|
————————————————
|
||||||
${green}1.${plain} Install
|
${green}1.${plain} Install x-ui
|
||||||
${green}2.${plain} Update
|
${green}2.${plain} Update x-ui
|
||||||
${green}3.${plain} Custom Version
|
${green}3.${plain} Uninstall x-ui
|
||||||
${green}4.${plain} Uninstall
|
|
||||||
————————————————
|
————————————————
|
||||||
${green}5.${plain} Reset Username & Password & Secret Token
|
${green}4.${plain} Reset Username & Password & Secret Token
|
||||||
${green}6.${plain} Reset Settings
|
${green}5.${plain} Reset Panel Settings
|
||||||
${green}7.${plain} Change Port
|
${green}6.${plain} Change Panel Port
|
||||||
${green}8.${plain} View Current Settings
|
${green}7.${plain} View Current Panel Settings
|
||||||
————————————————
|
————————————————
|
||||||
${green}9.${plain} Start
|
${green}8.${plain} Start x-ui
|
||||||
${green}10.${plain} Stop
|
${green}9.${plain} Stop x-ui
|
||||||
${green}11.${plain} Restart
|
${green}10.${plain} Restart x-ui
|
||||||
${green}12.${plain} Check Status
|
${green}11.${plain} Check x-ui Status
|
||||||
${green}13.${plain} Check Logs
|
${green}12.${plain} Check x-ui Logs
|
||||||
————————————————
|
————————————————
|
||||||
${green}14.${plain} Enable x-ui On System Startup
|
${green}13.${plain} Enable x-ui On System Startup
|
||||||
${green}15.${plain} Disable x-ui On System Startup
|
${green}14.${plain} Disable x-ui On System Startup
|
||||||
————————————————
|
————————————————
|
||||||
${green}16.${plain} SSL Certificate Management
|
${green}15.${plain} SSL Certificate Management
|
||||||
${green}17.${plain} Cloudflare SSL Certificate
|
${green}16.${plain} Cloudflare SSL Certificate
|
||||||
${green}18.${plain} IP Limit Management
|
${green}17.${plain} IP Limit Management
|
||||||
${green}19.${plain} WARP Management
|
${green}18.${plain} WARP Management
|
||||||
————————————————
|
————————————————
|
||||||
${green}20.${plain} Enable BBR
|
${green}19.${plain} Enable BBR
|
||||||
${green}21.${plain} Update Geo Files
|
${green}20.${plain} Update Geo Files
|
||||||
${green}22.${plain} Active Firewall and open ports
|
${green}21.${plain} Active Firewall and open ports
|
||||||
${green}23.${plain} Speedtest by Ookla
|
${green}22.${plain} Speedtest by Ookla
|
||||||
"
|
"
|
||||||
show_status
|
show_status
|
||||||
echo && read -p "Please enter your selection [0-23]: " num
|
echo && read -p "Please enter your selection [0-22]: " num
|
||||||
|
|
||||||
case "${num}" in
|
case "${num}" in
|
||||||
0)
|
0)
|
||||||
|
@ -1100,70 +1077,67 @@ show_menu() {
|
||||||
check_install && update
|
check_install && update
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
check_install && custom_version
|
|
||||||
;;
|
|
||||||
4)
|
|
||||||
check_install && uninstall
|
check_install && uninstall
|
||||||
;;
|
;;
|
||||||
5)
|
4)
|
||||||
check_install && reset_user
|
check_install && reset_user
|
||||||
;;
|
;;
|
||||||
6)
|
5)
|
||||||
check_install && reset_config
|
check_install && reset_config
|
||||||
;;
|
;;
|
||||||
7)
|
6)
|
||||||
check_install && set_port
|
check_install && set_port
|
||||||
;;
|
;;
|
||||||
8)
|
7)
|
||||||
check_install && check_config
|
check_install && check_config
|
||||||
;;
|
;;
|
||||||
9)
|
8)
|
||||||
check_install && start
|
check_install && start
|
||||||
;;
|
;;
|
||||||
10)
|
9)
|
||||||
check_install && stop
|
check_install && stop
|
||||||
;;
|
;;
|
||||||
11)
|
10)
|
||||||
check_install && restart
|
check_install && restart
|
||||||
;;
|
;;
|
||||||
12)
|
11)
|
||||||
check_install && status
|
check_install && status
|
||||||
;;
|
;;
|
||||||
13)
|
12)
|
||||||
check_install && show_log
|
check_install && show_log
|
||||||
;;
|
;;
|
||||||
14)
|
13)
|
||||||
check_install && enable
|
check_install && enable
|
||||||
;;
|
;;
|
||||||
15)
|
14)
|
||||||
check_install && disable
|
check_install && disable
|
||||||
;;
|
;;
|
||||||
16)
|
15)
|
||||||
ssl_cert_issue_main
|
ssl_cert_issue_main
|
||||||
;;
|
;;
|
||||||
17)
|
16)
|
||||||
ssl_cert_issue_CF
|
ssl_cert_issue_CF
|
||||||
;;
|
;;
|
||||||
18)
|
17)
|
||||||
iplimit_main
|
iplimit_main
|
||||||
;;
|
;;
|
||||||
19)
|
18)
|
||||||
warp_cloudflare
|
warp_cloudflare
|
||||||
;;
|
;;
|
||||||
20)
|
19)
|
||||||
enable_bbr
|
enable_bbr
|
||||||
;;
|
;;
|
||||||
21)
|
20)
|
||||||
update_geo
|
update_geo
|
||||||
;;
|
;;
|
||||||
22)
|
21)
|
||||||
open_ports
|
open_ports
|
||||||
;;
|
;;
|
||||||
23)
|
22)
|
||||||
run_speedtest
|
run_speedtest
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
LOGE "Please enter the correct number [0-23]"
|
LOGE "Please enter the correct number [0-22]"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue