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-layout id="content-layout">
|
||||
<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>
|
||||
<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" }}'
|
||||
color="red"
|
||||
description='{{ i18n "secAlertSsl" }}'
|
||||
|
@ -158,6 +158,13 @@
|
|||
</a-alert>
|
||||
</transition>
|
||||
<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-row>
|
||||
<a-col :sm="12" :md="6">
|
||||
|
@ -220,8 +227,8 @@
|
|||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</transition>
|
||||
<transition name="list" appear>
|
||||
</a-col>
|
||||
<a-col>
|
||||
<a-card hoverable>
|
||||
<template #title>
|
||||
<a-space direction="horizontal">
|
||||
|
@ -651,6 +658,8 @@
|
|||
</a-table>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</transition>
|
||||
</a-spin>
|
||||
</a-layout-content>
|
||||
|
@ -766,7 +775,10 @@
|
|||
data: {
|
||||
themeSwitcher,
|
||||
persianDatepicker,
|
||||
spinning: false,
|
||||
loadingStates: {
|
||||
fetched: false,
|
||||
spinning: false
|
||||
},
|
||||
inbounds: [],
|
||||
dbInbounds: [],
|
||||
searchKey: '',
|
||||
|
@ -797,7 +809,7 @@
|
|||
},
|
||||
methods: {
|
||||
loading(spinning = true) {
|
||||
this.spinning = spinning;
|
||||
this.loadingStates.spinning = spinning;
|
||||
},
|
||||
getClientWithComment(email, inboundId) {
|
||||
const dbInbound = this.dbInbounds.find(inbound => inbound.id === inboundId);
|
||||
|
@ -819,6 +831,7 @@
|
|||
}
|
||||
|
||||
await this.getOnlineUsers();
|
||||
|
||||
this.setInbounds(msg.obj);
|
||||
setTimeout(() => {
|
||||
this.refreshing = false;
|
||||
|
@ -870,6 +883,9 @@
|
|||
this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound);
|
||||
}
|
||||
}
|
||||
if (!this.loadingStates.fetched) {
|
||||
this.loadingStates.fetched = true
|
||||
}
|
||||
if(this.enableFilter){
|
||||
this.filterInbounds();
|
||||
} else {
|
||||
|
@ -1541,9 +1557,9 @@
|
|||
},
|
||||
async manualRefresh() {
|
||||
if (!this.refreshing) {
|
||||
this.spinning = true;
|
||||
this.loadingStates.spinning = true;
|
||||
await this.getDBInbounds();
|
||||
this.spinning = false;
|
||||
this.loadingStates.spinning = false;
|
||||
}
|
||||
},
|
||||
pagination(obj){
|
||||
|
|
|
@ -4,15 +4,6 @@
|
|||
.ant-layout-content {
|
||||
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 {
|
||||
color: var(--dark-color-text-primary);
|
||||
|
@ -84,9 +75,9 @@
|
|||
<a-sidebar></a-sidebar>
|
||||
<a-layout id="content-layout">
|
||||
<a-layout-content>
|
||||
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
||||
<a-spin :spinning="loadingStates.spinning" :delay="200" :tip="loadingTip">
|
||||
<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" }}'
|
||||
color="red"
|
||||
description='{{ i18n "secAlertSsl" }}'
|
||||
|
@ -95,15 +86,15 @@
|
|||
</transition>
|
||||
<transition name="list" appear>
|
||||
<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-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||
</a-card>
|
||||
</a-row>
|
||||
<a-row v-else>
|
||||
<a-row>
|
||||
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||
<a-col>
|
||||
<a-card hoverable>
|
||||
<a-row>
|
||||
<a-row :gutter="[0, isMobile ? 16 : 0]">
|
||||
<a-col :sm="24" :md="12">
|
||||
<a-row>
|
||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||
|
@ -153,7 +144,7 @@
|
|||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-row>
|
||||
</a-col>
|
||||
<a-col :sm="24" :lg="12">
|
||||
<a-card hoverable>
|
||||
<template #title>
|
||||
|
@ -488,7 +479,7 @@
|
|||
}
|
||||
|
||||
class Status {
|
||||
constructor(data, isLoaded = false) {
|
||||
constructor(data) {
|
||||
this.cpu = new CurTotal(0, 0);
|
||||
this.cpuCores = 0;
|
||||
this.logicalPro = 0;
|
||||
|
@ -512,7 +503,6 @@
|
|||
return;
|
||||
}
|
||||
|
||||
this.isLoaded = isLoaded;
|
||||
this.cpu = new CurTotal(data.cpu, 100);
|
||||
this.cpuCores = data.cpuCores;
|
||||
this.logicalPro = data.logicalPro;
|
||||
|
@ -632,32 +622,39 @@
|
|||
mixins: [MediaQueryMixin],
|
||||
data: {
|
||||
themeSwitcher,
|
||||
loadingStates: {
|
||||
fetched: false,
|
||||
spinning: false
|
||||
},
|
||||
status: new Status(),
|
||||
versionModal,
|
||||
logModal,
|
||||
backupModal,
|
||||
spinning: false,
|
||||
loadingTip: '{{ i18n "loading"}}',
|
||||
showAlert: false,
|
||||
showIp: false
|
||||
},
|
||||
methods: {
|
||||
loading(spinning, tip = '{{ i18n "loading"}}') {
|
||||
this.spinning = spinning;
|
||||
this.loadingStates.spinning = spinning;
|
||||
this.loadingTip = tip;
|
||||
},
|
||||
async getStatus() {
|
||||
try {
|
||||
const msg = await HttpUtil.post('/server/status');
|
||||
if (msg.success) {
|
||||
if (!this.loadingStates.fetched) {
|
||||
this.loadingStates.fetched = true;
|
||||
}
|
||||
|
||||
this.setStatus(msg.obj, true);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to get status:", e);
|
||||
}
|
||||
},
|
||||
setStatus(data, isLoaded = false) {
|
||||
this.status = new Status(data, isLoaded);
|
||||
setStatus(data) {
|
||||
this.status = new Status(data);
|
||||
},
|
||||
async openSelectV2rayVersion() {
|
||||
this.loading(true);
|
||||
|
|
|
@ -65,9 +65,9 @@
|
|||
<a-sidebar></a-sidebar>
|
||||
<a-layout id="content-layout">
|
||||
<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>
|
||||
<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" }}'
|
||||
color="red"
|
||||
show-icon closable>
|
||||
|
@ -77,8 +77,16 @@
|
|||
</template>
|
||||
</a-alert>
|
||||
</transition>
|
||||
<a-space direction="vertical">
|
||||
<a-card hoverable :style="{ marginBottom: '.5rem', overflowX: 'hidden' }">
|
||||
<transition name="list" appear>
|
||||
<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-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||
<a-space direction="horizontal">
|
||||
|
@ -99,24 +107,49 @@
|
|||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col>
|
||||
<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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</transition>
|
||||
</a-spin>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
|
@ -132,10 +165,14 @@
|
|||
<script>
|
||||
const app = new Vue({
|
||||
delimiters: ['[[', ']]'],
|
||||
mixins: [MediaQueryMixin],
|
||||
el: '#app',
|
||||
data: {
|
||||
themeSwitcher,
|
||||
spinning: false,
|
||||
loadingStates: {
|
||||
fetched: false,
|
||||
spinning: false
|
||||
},
|
||||
oldAllSetting: new AllSetting(),
|
||||
allSetting: new AllSetting(),
|
||||
saveBtnDisable: true,
|
||||
|
@ -248,13 +285,16 @@
|
|||
},
|
||||
methods: {
|
||||
loading(spinning = true) {
|
||||
this.spinning = spinning;
|
||||
this.loadingStates.spinning = spinning;
|
||||
},
|
||||
async getAllSetting() {
|
||||
this.loading(true);
|
||||
const msg = await HttpUtil.post("/panel/setting/all");
|
||||
this.loading(false);
|
||||
|
||||
if (msg.success) {
|
||||
if (!this.loadingStates.fetched) {
|
||||
this.loadingStates.fetched = true
|
||||
}
|
||||
|
||||
this.oldAllSetting = new AllSetting(msg.obj);
|
||||
this.allSetting = new AllSetting(msg.obj);
|
||||
app.changeRemarkSample();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{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"}}'
|
||||
description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
||||
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" :style="{ margin: '10px 0' }"
|
||||
|
|
|
@ -9,25 +9,31 @@
|
|||
margin: 24px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.ant-tabs-nav .ant-tabs-tab {
|
||||
margin: 0;
|
||||
padding: 12px .5rem;
|
||||
}
|
||||
|
||||
.ant-table-thead>tr>th,
|
||||
.ant-table-tbody>tr>td {
|
||||
padding: 10px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-bar {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ant-list-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ant-list-item>li {
|
||||
padding: 10px 20px !important;
|
||||
}
|
||||
|
||||
.ant-collapse-content-box .ant-alert {
|
||||
margin-block-end: 12px;
|
||||
}
|
||||
|
@ -39,24 +45,31 @@
|
|||
<a-sidebar></a-sidebar>
|
||||
<a-layout id="content-layout">
|
||||
<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>
|
||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
||||
message='{{ i18n "secAlertTitle" }}'
|
||||
color="red"
|
||||
description='{{ i18n "secAlertSsl" }}'
|
||||
show-icon closable>
|
||||
<a-alert type="error" v-if="showAlert && loadingStates.fetched" :style="{ marginBottom: '10px' }" message='{{ i18n "secAlertTitle" }}'
|
||||
color="red" description='{{ i18n "secAlertSsl" }}' show-icon closable>
|
||||
</a-alert>
|
||||
</transition>
|
||||
<a-space direction="vertical">
|
||||
<a-card hoverable :style="{ marginBottom: '.5rem' }">
|
||||
<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 hoverable>
|
||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||
<a-space direction="horizontal">
|
||||
<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-popover v-if="restartResult"
|
||||
:overlay-class-name="themeSwitcher.currentTheme">
|
||||
<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-popover v-if="restartResult" :overlay-class-name="themeSwitcher.currentTheme">
|
||||
<span slot="title">{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
||||
<template slot="content">
|
||||
<span :style="{ maxWidth: '400px' }" v-for="line in restartResult.split('\n')">[[ line ]]</span>
|
||||
|
@ -68,40 +81,73 @@
|
|||
<a-col :xs="24" :sm="14">
|
||||
<template>
|
||||
<div>
|
||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
||||
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }" message='{{ i18n "pages.settings.infoDesc" }}' show-icon>
|
||||
<a-back-top :target="() => document.getElementById('content-layout')"
|
||||
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>
|
||||
</div>
|
||||
</template>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
<a-tabs class="ant-card-dark-box-nohover" default-active-key="1"
|
||||
@change="(activeKey) => { this.changePage(activeKey); }"
|
||||
</a-col>
|
||||
<a-col>
|
||||
<a-tabs default-active-key="tpl-basic" @change="(activeKey) => { this.changePage(activeKey); }"
|
||||
: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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</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" . }}
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</transition>
|
||||
</a-spin>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
|
@ -133,20 +179,28 @@
|
|||
<script>
|
||||
const rulesColumns = [
|
||||
{ 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: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'sourcePort', align: 'center', width: 10, ellipsis: true } ]},
|
||||
{ title: '{{ i18n "pages.inbounds.network"}}', children: [
|
||||
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'sourcePort', align: 'center', width: 10, ellipsis: true }]
|
||||
},
|
||||
{
|
||||
title: '{{ i18n "pages.inbounds.network"}}', children: [
|
||||
{ title: 'L4', dataIndex: 'network', align: 'center', width: 10 },
|
||||
{ title: '{{ i18n "protocol" }}', dataIndex: 'protocol', align: 'center', width: 15, ellipsis: true },
|
||||
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 10, ellipsis: true } ]},
|
||||
{ title: '{{ i18n "pages.xray.rules.dest"}}', children: [
|
||||
{ title: 'Attrs', dataIndex: 'attrs', align: 'center', width: 10, ellipsis: true }]
|
||||
},
|
||||
{
|
||||
title: '{{ i18n "pages.xray.rules.dest"}}', children: [
|
||||
{ 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.inbounds.port" }}', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]},
|
||||
{ title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
||||
{ title: '{{ i18n "pages.inbounds.port" }}', dataIndex: 'port', align: 'center', width: 10, ellipsis: true }]
|
||||
},
|
||||
{
|
||||
title: '{{ i18n "pages.xray.rules.inbound"}}', children: [
|
||||
{ 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.balancer"}}', dataIndex: 'balancerTag', align: 'center', width: 15 },
|
||||
];
|
||||
|
@ -200,7 +254,10 @@
|
|||
data: {
|
||||
themeSwitcher,
|
||||
isDarkTheme: themeSwitcher.isDarkTheme,
|
||||
spinning: false,
|
||||
loadingStates: {
|
||||
fetched: false,
|
||||
spinning: false
|
||||
},
|
||||
oldXraySetting: '',
|
||||
xraySetting: '',
|
||||
inboundTags: [],
|
||||
|
@ -329,7 +386,7 @@
|
|||
},
|
||||
methods: {
|
||||
loading(spinning = true) {
|
||||
this.spinning = spinning;
|
||||
this.loadingStates.spinning = spinning;
|
||||
},
|
||||
async getOutboundsTraffic() {
|
||||
const msg = await HttpUtil.get("/panel/xray/getOutboundsTraffic");
|
||||
|
@ -338,10 +395,13 @@
|
|||
}
|
||||
},
|
||||
async getXraySetting() {
|
||||
this.loading(true);
|
||||
const msg = await HttpUtil.post("/panel/xray/");
|
||||
this.loading(false);
|
||||
|
||||
if (msg.success) {
|
||||
if (!this.loadingStates.fetched) {
|
||||
this.loadingStates.fetched = true
|
||||
}
|
||||
|
||||
result = JSON.parse(msg.obj);
|
||||
xs = JSON.stringify(result.xraySetting, null, 2);
|
||||
this.oldXraySetting = xs;
|
||||
|
|
Loading…
Reference in a new issue