mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-01 20:42:07 +00:00
refactor: use new page templates
This commit is contained in:
parent
1644904755
commit
83eccb6ce3
8 changed files with 756 additions and 753 deletions
|
@ -1,31 +0,0 @@
|
||||||
{{define "head"}}
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="renderer" content="webkit">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue/antd.min.css">
|
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.min.css?{{ .cur_ver }}">
|
|
||||||
<style>
|
|
||||||
[v-cloak] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* vazirmatn-regular - arabic_latin_latin-ext */
|
|
||||||
@font-face {
|
|
||||||
font-display: swap;
|
|
||||||
font-family: 'Vazirmatn';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url('{{ .base_path }}assets/Vazirmatn-UI-NL-Regular.woff2') format('woff2');
|
|
||||||
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC, U+0030-0039;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Vazirmatn', 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
|
|
||||||
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji',
|
|
||||||
'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<title>{{ .host }} – {{ i18n .title}}</title>
|
|
||||||
</head>
|
|
||||||
<div id="message"></div>
|
|
||||||
{{end}}
|
|
|
@ -1,14 +0,0 @@
|
||||||
{{define "js"}}
|
|
||||||
<script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/qs/qs.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
|
|
||||||
<script>
|
|
||||||
const basePath = '{{ .base_path }}';
|
|
||||||
axios.defaults.baseURL = basePath;
|
|
||||||
</script>
|
|
||||||
{{end}}
|
|
58
web/html/common/page.html
Normal file
58
web/html/common/page.html
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{{ define "page/head_start" }}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="renderer" content="webkit">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue/antd.min.css">
|
||||||
|
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.min.css?{{ .cur_ver }}">
|
||||||
|
<style>
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* vazirmatn-regular - arabic_latin_latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Vazirmatn';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('{{ .base_path }}assets/Vazirmatn-UI-NL-Regular.woff2') format('woff2');
|
||||||
|
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC, U+0030-0039;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Vazirmatn', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>{{ .host }} – {{ i18n .title}}</title>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/head_end" }}
|
||||||
|
</head>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_start" }}
|
||||||
|
<body>
|
||||||
|
<div id="message"></div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_scripts" }}
|
||||||
|
<script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/qs/qs.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
|
||||||
|
<script>
|
||||||
|
const basePath = '{{ .base_path }}';
|
||||||
|
axios.defaults.baseURL = basePath;
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_end" }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
.ant-table:not(.ant-table-expanded-row .ant-table) {
|
.ant-table:not(.ant-table-expanded-row .ant-table) {
|
||||||
outline: 1px solid #f0f0f0;
|
outline: 1px solid #f0f0f0;
|
||||||
|
@ -143,8 +141,9 @@
|
||||||
padding: 12px 2px;
|
padding: 12px 2px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
<body>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
|
@ -657,7 +656,7 @@
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
{{template "page/body_scripts" .}}
|
||||||
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/uri/URI.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/uri/URI.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/js/model/inbound.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/inbound.js?{{ .cur_ver }}"></script>
|
||||||
|
@ -666,6 +665,13 @@
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
{{template "component/aCustomStatistic" .}}
|
{{template "component/aCustomStatistic" .}}
|
||||||
{{template "component/aPersianDatepicker" .}}
|
{{template "component/aPersianDatepicker" .}}
|
||||||
|
{{template "modals/inboundModal"}}
|
||||||
|
{{template "modals/promptModal"}}
|
||||||
|
{{template "modals/qrcodeModal"}}
|
||||||
|
{{template "modals/textModal"}}
|
||||||
|
{{template "modals/inboundInfoModal"}}
|
||||||
|
{{template "modals/clientsModal"}}
|
||||||
|
{{template "modals/clientsBulkModal"}}
|
||||||
<script>
|
<script>
|
||||||
const columns = [{
|
const columns = [{
|
||||||
title: "ID",
|
title: "ID",
|
||||||
|
@ -1607,13 +1613,4 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
{{ template "page/body_end" .}}
|
||||||
{{template "modals/inboundModal"}}
|
|
||||||
{{template "modals/promptModal"}}
|
|
||||||
{{template "modals/qrcodeModal"}}
|
|
||||||
{{template "modals/textModal"}}
|
|
||||||
{{template "modals/inboundInfoModal"}}
|
|
||||||
{{template "modals/clientsModal"}}
|
|
||||||
{{template "modals/clientsBulkModal"}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
|
@ -79,384 +77,385 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
<body>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
color="red"
|
color="red"
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
description='{{ i18n "secAlertSsl" }}'
|
||||||
show-icon closable>
|
show-icon closable>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<template>
|
<template>
|
||||||
<a-row v-if="!status.isLoaded">
|
<a-row v-if="!status.isLoaded">
|
||||||
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
|
</a-card>
|
||||||
|
</a-row>
|
||||||
|
<a-row v-else>
|
||||||
|
<a-row>
|
||||||
|
<a-card hoverable>
|
||||||
|
<a-row>
|
||||||
|
<a-col :sm="24" :md="12">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.cpu.color"
|
||||||
|
:percent="status.cpu.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.cpu" }}:</b> [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
|
||||||
|
<a-tooltip>
|
||||||
|
<a-icon type="area-chart"></a-icon>
|
||||||
|
<template slot="title">
|
||||||
|
<div><b>{{ i18n "pages.index.logicalProcessors" }}:</b> [[ (status.logicalPro) ]]</div>
|
||||||
|
<div><b>{{ i18n "pages.index.frequency" }}:</b> [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
||||||
|
</template>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.mem.color"
|
||||||
|
:percent="status.mem.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.memory"}}:</b> [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-col>
|
||||||
|
<a-col :sm="24" :md="12">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.swap.color"
|
||||||
|
:percent="status.swap.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.swap" }}:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.disk.color"
|
||||||
|
:percent="status.disk.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.storage"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row v-else>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-row>
|
<a-card hoverable>
|
||||||
<a-card hoverable>
|
<template #title>
|
||||||
<a-row>
|
<a-space direction="horizontal">
|
||||||
<a-col :sm="24" :md="12">
|
<span>{{ i18n "pages.index.xrayStatus" }}</span>
|
||||||
<a-row>
|
<a-tag v-if="isMobile && status.xray.version != 'Unknown'" color="green">
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
v[[ status.xray.version ]]
|
||||||
<a-progress type="dashboard" status="normal"
|
</a-tag>
|
||||||
:stroke-color="status.cpu.color"
|
</a-space>
|
||||||
:percent="status.cpu.percent"></a-progress>
|
</template>
|
||||||
<div>
|
<template #extra>
|
||||||
<b>{{ i18n "pages.index.cpu" }}:</b> [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
|
<template v-if="status.xray.state != 'error'">
|
||||||
<a-tooltip>
|
<a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
|
||||||
<a-icon type="area-chart"></a-icon>
|
|
||||||
<template slot="title">
|
|
||||||
<div><b>{{ i18n "pages.index.logicalProcessors" }}:</b> [[ (status.logicalPro) ]]</div>
|
|
||||||
<div><b>{{ i18n "pages.index.frequency" }}:</b> [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.mem.color"
|
|
||||||
:percent="status.mem.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.memory"}}:</b> [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-col>
|
|
||||||
<a-col :sm="24" :md="12">
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.swap.color"
|
|
||||||
:percent="status.swap.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.swap" }}:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.disk.color"
|
|
||||||
:percent="status.disk.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.storage"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-row>
|
|
||||||
<a-col :sm="24" :lg="12">
|
|
||||||
<a-card hoverable>
|
|
||||||
<template #title>
|
|
||||||
<a-space direction="horizontal">
|
|
||||||
<span>{{ i18n "pages.index.xrayStatus" }}</span>
|
|
||||||
<a-tag v-if="isMobile && status.xray.version != 'Unknown'" color="green">
|
|
||||||
v[[ status.xray.version ]]
|
|
||||||
</a-tag>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template v-else>
|
||||||
<template v-if="status.xray.state != 'error'">
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
<a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
|
<span slot="title">
|
||||||
</template>
|
<a-row type="flex" align="middle" justify="space-between">
|
||||||
<template v-else>
|
<a-col>
|
||||||
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
<span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
||||||
<span slot="title">
|
</a-col>
|
||||||
<a-row type="flex" align="middle" justify="space-between">
|
<a-col>
|
||||||
<a-col>
|
<a-icon type="bars" :style="{ cursor: 'pointer', float: 'right' }" @click="openLogs()"></a-tag>
|
||||||
<span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
</a-col>
|
||||||
</a-col>
|
</a-row>
|
||||||
<a-col>
|
|
||||||
<a-icon type="bars" :style="{ cursor: 'pointer', float: 'right' }" @click="openLogs()"></a-tag>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</span>
|
|
||||||
<template slot="content">
|
|
||||||
<span :style="{ maxWidth: '400px' }" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</span>
|
|
||||||
</template>
|
|
||||||
<a-badge :text="status.xray.stateMsg" :color="status.xray.color"/>
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template #actions>
|
|
||||||
<a-space direction="horizontal" @click="stopXrayService" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="poweroff"></a-icon>
|
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.stopXray" }}</span>
|
|
||||||
</a-space>
|
|
||||||
<a-space direction="horizontal" @click="restartXrayService" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="reload"></a-icon>
|
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.restartXray" }}</span>
|
|
||||||
</a-space>
|
|
||||||
<a-space direction="horizontal" @click="openSelectV2rayVersion" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="tool"></a-icon>
|
|
||||||
<span v-if="!isMobile">
|
|
||||||
[[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
|
|
||||||
</span>
|
</span>
|
||||||
</a-space>
|
<template slot="content">
|
||||||
|
<span :style="{ maxWidth: '400px' }" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</span>
|
||||||
|
</template>
|
||||||
|
<a-badge :text="status.xray.stateMsg" :color="status.xray.color"/>
|
||||||
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
</a-card>
|
</template>
|
||||||
</a-col>
|
<template #actions>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-space direction="horizontal" @click="stopXrayService" :style="{ justifyContent: 'center' }">
|
||||||
<a-card title='{{ i18n "menu.link" }}' hoverable>
|
<a-icon type="poweroff"></a-icon>
|
||||||
<template #actions>
|
<span v-if="!isMobile">{{ i18n "pages.index.stopXray" }}</span>
|
||||||
<a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
|
</a-space>
|
||||||
<a-icon type="bars"></a-icon>
|
<a-space direction="horizontal" @click="restartXrayService" :style="{ justifyContent: 'center' }">
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
|
<a-icon type="reload"></a-icon>
|
||||||
</a-space>
|
<span v-if="!isMobile">{{ i18n "pages.index.restartXray" }}</span>
|
||||||
<a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
|
</a-space>
|
||||||
<a-icon type="control"></a-icon>
|
<a-space direction="horizontal" @click="openSelectV2rayVersion" :style="{ justifyContent: 'center' }">
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
|
<a-icon type="tool"></a-icon>
|
||||||
</a-space>
|
<span v-if="!isMobile">
|
||||||
<a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
|
[[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
|
||||||
<a-icon type="cloud-server"></a-icon>
|
</span>
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.backup" }}</span>
|
</a-space>
|
||||||
</a-space>
|
</template>
|
||||||
</template>
|
</a-card>
|
||||||
</a-card>
|
</a-col>
|
||||||
</a-col>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-card title='{{ i18n "menu.link" }}' hoverable>
|
||||||
<a-card title='3X-UI' hoverable>
|
<template #actions>
|
||||||
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank">
|
<a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
|
||||||
<a-tag color="green">
|
<a-icon type="bars"></a-icon>
|
||||||
<span>v{{ .cur_ver }}</span>
|
<span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
|
||||||
</a-tag>
|
</a-space>
|
||||||
</a>
|
<a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
|
||||||
<a rel="noopener" href="https://t.me/XrayUI" target="_blank">
|
<a-icon type="control"></a-icon>
|
||||||
<a-tag color="green">
|
<span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
|
||||||
<span>@XrayUI</span>
|
</a-space>
|
||||||
</a-tag>
|
<a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
|
||||||
</a>
|
<a-icon type="cloud-server"></a-icon>
|
||||||
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/wiki" target="_blank">
|
<span v-if="!isMobile">{{ i18n "pages.index.backup" }}</span>
|
||||||
<a-tag>
|
</a-space>
|
||||||
<span>{{ i18n "pages.index.documentation" }}</span>
|
</template>
|
||||||
</a-tag>
|
</a-card>
|
||||||
</a>
|
</a-col>
|
||||||
</a-card>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-col>
|
<a-card title='3X-UI' hoverable>
|
||||||
<a-col :sm="24" :lg="12">
|
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank">
|
||||||
<a-card title='{{ i18n "pages.index.operationHours" }}' hoverable>
|
|
||||||
<a-tag :color="status.xray.color">Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]</a-tag>
|
|
||||||
<a-tag color="green">OS: [[ TimeFormatter.formatSecond(status.uptime) ]]</a-tag>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
<a-col :sm="24" :lg="12">
|
|
||||||
<a-card title='{{ i18n "pages.index.systemLoad" }}' hoverable>
|
|
||||||
<a-tag color="green">
|
<a-tag color="green">
|
||||||
<a-tooltip>
|
<span>v{{ .cur_ver }}</span>
|
||||||
[[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
|
|
||||||
<template slot="title">
|
|
||||||
{{ i18n "pages.index.systemLoadDesc" }}
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-card>
|
</a>
|
||||||
</a-col>
|
<a rel="noopener" href="https://t.me/XrayUI" target="_blank">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-tag color="green">
|
||||||
<a-card title='{{ i18n "usage"}}' hoverable>
|
<span>@XrayUI</span>
|
||||||
<a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
|
</a-tag>
|
||||||
<a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
|
</a>
|
||||||
</a-card>
|
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/wiki" target="_blank">
|
||||||
</a-col>
|
<a-tag color="purple">
|
||||||
<a-col :sm="24" :lg="12">
|
<span>{{ i18n "pages.index.documentation" }}</span>
|
||||||
<a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
|
</a-tag>
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
</a>
|
||||||
<a-col :span="12">
|
</a-card>
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
|
</a-col>
|
||||||
<template #prefix>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-icon type="arrow-up" />
|
<a-card title='{{ i18n "pages.index.operationHours" }}' hoverable>
|
||||||
</template>
|
<a-tag :color="status.xray.color">Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]</a-tag>
|
||||||
<template #suffix>
|
<a-tag color="green">OS: [[ TimeFormatter.formatSecond(status.uptime) ]]</a-tag>
|
||||||
/s
|
</a-card>
|
||||||
</template>
|
</a-col>
|
||||||
</a-custom-statistic>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-col>
|
<a-card title='{{ i18n "pages.index.systemLoad" }}' hoverable>
|
||||||
<a-col :span="12">
|
<a-tag color="green">
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.download" }}' :value="SizeFormatter.sizeFormat(status.netIO.down)">
|
<a-tooltip>
|
||||||
<template #prefix>
|
[[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
|
||||||
<a-icon type="arrow-down" />
|
<template slot="title">
|
||||||
</template>
|
{{ i18n "pages.index.systemLoadDesc" }}
|
||||||
<template #suffix>
|
</template>
|
||||||
/s
|
</a-tooltip>
|
||||||
</template>
|
</a-tag>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "usage"}}' hoverable>
|
||||||
</a-col>
|
<a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
|
||||||
<a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
|
</a-card>
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :sm="24" :lg="12">
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.sent" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.sent)">
|
<a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
|
||||||
<template #prefix>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-icon type="cloud-upload" />
|
<a-col :span="12">
|
||||||
</template>
|
<a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
|
||||||
</a-custom-statistic>
|
<template #prefix>
|
||||||
</a-col>
|
<a-icon type="arrow-up" />
|
||||||
<a-col :span="12">
|
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.received" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.recv)">
|
|
||||||
<template #prefix>
|
|
||||||
<a-icon type="cloud-download" />
|
|
||||||
</template>
|
|
||||||
</a-custom-statistic>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
<a-col :sm="24" :lg="12">
|
|
||||||
<a-card title='{{ i18n "pages.index.ipAddresses" }}' hoverable>
|
|
||||||
<template #extra>
|
|
||||||
<a-tooltip :placement="isMobile ? 'topRight' : 'top'">
|
|
||||||
<template #title>
|
|
||||||
{{ i18n "pages.index.toggleIpVisibility" }}
|
|
||||||
</template>
|
</template>
|
||||||
<a-icon :type="showIp ? 'eye' : 'eye-invisible'" :style="{ fontSize: '1rem' }" @click="showIp = !showIp"></a-icon>
|
<template #suffix>
|
||||||
</a-tooltip>
|
/s
|
||||||
</template>
|
</template>
|
||||||
<a-row :class="showIp ? 'ip-visible' : 'ip-hidden'" :gutter="isMobile ? [8,8] : 0">
|
</a-custom-statistic>
|
||||||
<a-col :span="isMobile ? 24 : 12">
|
</a-col>
|
||||||
<a-custom-statistic title="IPv4" :value="status.publicIP.ipv4">
|
<a-col :span="12">
|
||||||
<template #prefix>
|
<a-custom-statistic title='{{ i18n "pages.index.download" }}' :value="SizeFormatter.sizeFormat(status.netIO.down)">
|
||||||
<a-icon type="global" />
|
<template #prefix>
|
||||||
</template>
|
<a-icon type="arrow-down" />
|
||||||
</a-custom-statistic>
|
</template>
|
||||||
</a-col>
|
<template #suffix>
|
||||||
<a-col :span="isMobile ? 24 : 12">
|
/s
|
||||||
<a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="global" />
|
</a-col>
|
||||||
</template>
|
</a-row>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
|
||||||
</a-col>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-col :span="12">
|
||||||
<a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
|
<a-custom-statistic title='{{ i18n "pages.index.sent" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.sent)">
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
<template #prefix>
|
||||||
<a-col :span="12">
|
<a-icon type="cloud-upload" />
|
||||||
<a-custom-statistic title="TCP" :value="status.tcpCount">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="swap" />
|
</a-col>
|
||||||
</template>
|
<a-col :span="12">
|
||||||
</a-custom-statistic>
|
<a-custom-statistic title='{{ i18n "pages.index.received" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.recv)">
|
||||||
</a-col>
|
<template #prefix>
|
||||||
<a-col :span="12">
|
<a-icon type="cloud-download" />
|
||||||
<a-custom-statistic title="UDP" :value="status.udpCount">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="swap" />
|
</a-col>
|
||||||
</template>
|
</a-row>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "pages.index.ipAddresses" }}' hoverable>
|
||||||
</a-col>
|
<template #extra>
|
||||||
</a-row>
|
<a-tooltip :placement="isMobile ? 'topRight' : 'top'">
|
||||||
</template>
|
<template #title>
|
||||||
</transition>
|
{{ i18n "pages.index.toggleIpVisibility" }}
|
||||||
</a-spin>
|
</template>
|
||||||
</a-layout-content>
|
<a-icon :type="showIp ? 'eye' : 'eye-invisible'" :style="{ fontSize: '1rem' }" @click="showIp = !showIp"></a-icon>
|
||||||
</a-layout>
|
</a-tooltip>
|
||||||
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
</template>
|
||||||
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
<a-row :class="showIp ? 'ip-visible' : 'ip-hidden'" :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-collapse default-active-key="1">
|
<a-col :span="isMobile ? 24 : 12">
|
||||||
<a-collapse-panel key="1" header='Xray'>
|
<a-custom-statistic title="IPv4" :value="status.publicIP.ipv4">
|
||||||
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }" message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
<template #prefix>
|
||||||
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
<a-icon type="global" />
|
||||||
<a-list-item class="ant-version-list-item" v-for="version, index in versionModal.versions">
|
</template>
|
||||||
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
</a-custom-statistic>
|
||||||
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
</a-col>
|
||||||
</a-list-item>
|
<a-col :span="isMobile ? 24 : 12">
|
||||||
</a-list>
|
<a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
|
||||||
</a-collapse-panel>
|
<template #prefix>
|
||||||
<a-collapse-panel key="2" header='Geofiles'>
|
<a-icon type="global" />
|
||||||
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
</template>
|
||||||
<a-list-item class="ant-version-list-item" v-for="file, index in ['geosite.dat', 'geoip.dat', 'geosite_IR.dat', 'geoip_IR.dat', 'geosite_RU.dat', 'geoip_RU.dat']">
|
</a-custom-statistic>
|
||||||
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ file ]]</a-tag>
|
</a-col>
|
||||||
<a-icon type="reload" @click="updateGeofile(file)" :style="{ marginRight: '8px' }"/>
|
</a-row>
|
||||||
</a-list-item>
|
</a-card>
|
||||||
</a-list>
|
</a-col>
|
||||||
</a-collapse-panel>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-collapse>
|
<a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
|
||||||
</a-modal>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-modal id="log-modal" v-model="logModal.visible"
|
<a-col :span="12">
|
||||||
:closable="true" @cancel="() => logModal.visible = false"
|
<a-custom-statistic title="TCP" :value="status.tcpCount">
|
||||||
:class="themeSwitcher.currentTheme"
|
<template #prefix>
|
||||||
width="800px" footer="">
|
<a-icon type="swap" />
|
||||||
<template slot="title">
|
</template>
|
||||||
{{ i18n "pages.index.logs" }}
|
</a-custom-statistic>
|
||||||
<a-icon :spin="logModal.loading"
|
</a-col>
|
||||||
type="sync"
|
<a-col :span="12">
|
||||||
:style="{ verticalAlign: 'middle', marginLeft: '10px' }"
|
<a-custom-statistic title="UDP" :value="status.udpCount">
|
||||||
:disabled="logModal.loading"
|
<template #prefix>
|
||||||
@click="openLogs()">
|
<a-icon type="swap" />
|
||||||
</a-icon>
|
</template>
|
||||||
</template>
|
</a-custom-statistic>
|
||||||
<a-form layout="inline">
|
</a-col>
|
||||||
<a-form-item :style="{ marginRight: '0.5rem' }">
|
</a-row>
|
||||||
<a-input-group compact>
|
</a-card>
|
||||||
<a-select size="small" v-model="logModal.rows" :style="{ width: '70px' }"
|
</a-col>
|
||||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
</a-row>
|
||||||
<a-select-option value="10">10</a-select-option>
|
</template>
|
||||||
<a-select-option value="20">20</a-select-option>
|
</transition>
|
||||||
<a-select-option value="50">50</a-select-option>
|
</a-spin>
|
||||||
<a-select-option value="100">100</a-select-option>
|
</a-layout-content>
|
||||||
<a-select-option value="500">500</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select size="small" v-model="logModal.level" :style="{ width: '95px' }"
|
|
||||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="debug">Debug</a-select-option>
|
|
||||||
<a-select-option value="info">Info</a-select-option>
|
|
||||||
<a-select-option value="notice">Notice</a-select-option>
|
|
||||||
<a-select-option value="warning">Warning</a-select-option>
|
|
||||||
<a-select-option value="err">Error</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-input-group>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item>
|
|
||||||
<a-checkbox v-model="logModal.syslog" @change="openLogs()">SysLog</a-checkbox>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item :style="{ float: 'right' }">
|
|
||||||
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(logModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<div class="ant-input" :style="{ height: 'auto', maxHeight: '500px', overflow: 'auto', marginTop: '0.5rem' }" v-html="logModal.formattedLogs"></div>
|
|
||||||
</a-modal>
|
|
||||||
<a-modal id="backup-modal"
|
|
||||||
v-model="backupModal.visible"
|
|
||||||
title='{{ i18n "pages.index.backupTitle" }}'
|
|
||||||
:closable="true"
|
|
||||||
footer=""
|
|
||||||
:class="themeSwitcher.currentTheme">
|
|
||||||
<a-list class="ant-backup-list" bordered :style="{ width: '100%' }">
|
|
||||||
<a-list-item class="ant-backup-list-item">
|
|
||||||
<a-list-item-meta>
|
|
||||||
<template #title>{{ i18n "pages.index.exportDatabase" }}</template>
|
|
||||||
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
|
|
||||||
</a-list-item-meta>
|
|
||||||
<a-button @click="exportDatabase()" type="primary" icon="download"/>
|
|
||||||
</a-list-item>
|
|
||||||
<a-list-item class="ant-backup-list-item">
|
|
||||||
<a-list-item-meta>
|
|
||||||
<template #title>{{ i18n "pages.index.importDatabase" }}</template>
|
|
||||||
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
|
|
||||||
</a-list-item-meta>
|
|
||||||
<a-button @click="importDatabase()" type="primary" icon="upload" />
|
|
||||||
</a-list-item>
|
|
||||||
</a-list>
|
|
||||||
</a-modal>
|
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
||||||
|
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
||||||
|
<a-collapse default-active-key="1">
|
||||||
|
<a-collapse-panel key="1" header='Xray'>
|
||||||
|
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }" message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
||||||
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="version, index in versionModal.versions">
|
||||||
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
||||||
|
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
<a-collapse-panel key="2" header='Geofiles'>
|
||||||
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="file, index in ['geosite.dat', 'geoip.dat', 'geosite_IR.dat', 'geoip_IR.dat', 'geosite_RU.dat', 'geoip_RU.dat']">
|
||||||
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ file ]]</a-tag>
|
||||||
|
<a-icon type="reload" @click="updateGeofile(file)" :style="{ marginRight: '8px' }"/>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
</a-collapse>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal id="log-modal" v-model="logModal.visible"
|
||||||
|
:closable="true" @cancel="() => logModal.visible = false"
|
||||||
|
:class="themeSwitcher.currentTheme"
|
||||||
|
width="800px" footer="">
|
||||||
|
<template slot="title">
|
||||||
|
{{ i18n "pages.index.logs" }}
|
||||||
|
<a-icon :spin="logModal.loading"
|
||||||
|
type="sync"
|
||||||
|
:style="{ verticalAlign: 'middle', marginLeft: '10px' }"
|
||||||
|
:disabled="logModal.loading"
|
||||||
|
@click="openLogs()">
|
||||||
|
</a-icon>
|
||||||
|
</template>
|
||||||
|
<a-form layout="inline">
|
||||||
|
<a-form-item :style="{ marginRight: '0.5rem' }">
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-select size="small" v-model="logModal.rows" :style="{ width: '70px' }"
|
||||||
|
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="10">10</a-select-option>
|
||||||
|
<a-select-option value="20">20</a-select-option>
|
||||||
|
<a-select-option value="50">50</a-select-option>
|
||||||
|
<a-select-option value="100">100</a-select-option>
|
||||||
|
<a-select-option value="500">500</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-select size="small" v-model="logModal.level" :style="{ width: '95px' }"
|
||||||
|
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="debug">Debug</a-select-option>
|
||||||
|
<a-select-option value="info">Info</a-select-option>
|
||||||
|
<a-select-option value="notice">Notice</a-select-option>
|
||||||
|
<a-select-option value="warning">Warning</a-select-option>
|
||||||
|
<a-select-option value="err">Error</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-checkbox v-model="logModal.syslog" @change="openLogs()">SysLog</a-checkbox>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :style="{ float: 'right' }">
|
||||||
|
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(logModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<div class="ant-input" :style="{ height: 'auto', maxHeight: '500px', overflow: 'auto', marginTop: '0.5rem' }" v-html="logModal.formattedLogs"></div>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal id="backup-modal"
|
||||||
|
v-model="backupModal.visible"
|
||||||
|
title='{{ i18n "pages.index.backupTitle" }}'
|
||||||
|
:closable="true"
|
||||||
|
footer=""
|
||||||
|
:class="themeSwitcher.currentTheme">
|
||||||
|
<a-list class="ant-backup-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-backup-list-item">
|
||||||
|
<a-list-item-meta>
|
||||||
|
<template #title>{{ i18n "pages.index.exportDatabase" }}</template>
|
||||||
|
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
<a-button @click="exportDatabase()" type="primary" icon="download"/>
|
||||||
|
</a-list-item>
|
||||||
|
<a-list-item class="ant-backup-list-item">
|
||||||
|
<a-list-item-meta>
|
||||||
|
<template #title>{{ i18n "pages.index.importDatabase" }}</template>
|
||||||
|
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
<a-button @click="importDatabase()" type="primary" icon="upload" />
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-modal>
|
||||||
|
</a-layout>
|
||||||
|
{{template "page/body_scripts" .}}
|
||||||
{{template "component/aSidebar" .}}
|
{{template "component/aSidebar" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
{{template "component/aCustomStatistic" .}}
|
{{template "component/aCustomStatistic" .}}
|
||||||
|
@ -788,5 +787,4 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
{{ template "page/body_end" .}}
|
||||||
</html>
|
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
html * {
|
html * {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
@ -453,174 +451,174 @@
|
||||||
margin: 2px 0 4px;
|
margin: 2px 0 4px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
<body>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-layout-content class="under" :style="{ minHeight: '0' }">
|
<a-layout-content class="under" :style="{ minHeight: '0' }">
|
||||||
<div class="waves-header">
|
<div class="waves-header">
|
||||||
<div class="waves-inner-header"></div>
|
<div class="waves-inner-header"></div>
|
||||||
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
|
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
|
||||||
<defs>
|
<defs>
|
||||||
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
|
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
|
||||||
</defs>
|
</defs>
|
||||||
<g class="parallax">
|
<g class="parallax">
|
||||||
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="7" fill="#c7ebe2" />
|
<use xlink:href="#gentle-wave" x="48" y="7" fill="#c7ebe2" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<a-row type="flex" justify="center" align="middle" :style="{ height: '100%', overflow: 'auto', overflowX: 'hidden' }">
|
<a-row type="flex" justify="center" align="middle" :style="{ height: '100%', overflow: 'auto', overflowX: 'hidden' }">
|
||||||
<a-col :xs="22" :sm="12" :md="10" :lg="8" :xl="6" :xxl="5" id="login" :style="{ margin: '3rem 0' }">
|
<a-col :xs="22" :sm="12" :md="10" :lg="8" :xl="6" :xxl="5" id="login" :style="{ margin: '3rem 0' }">
|
||||||
<div class="setting-section">
|
<div class="setting-section">
|
||||||
<a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}' placement="bottomRight" trigger="click">
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}' placement="bottomRight" trigger="click">
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<a-space direction="vertical" :size="10">
|
<a-space direction="vertical" :size="10">
|
||||||
<a-theme-switch-login></a-theme-switch-login>
|
<a-theme-switch-login></a-theme-switch-login>
|
||||||
<span>{{ i18n "pages.settings.language" }}</span>
|
<span>{{ i18n "pages.settings.language" }}</span>
|
||||||
<a-select ref="selectLang" :style="{ width: '100%' }" v-model="lang" @change="LanguageManager.setLanguage(lang)" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select ref="selectLang" :style="{ width: '100%' }" v-model="lang" @change="LanguageManager.setLanguage(lang)" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option :value="l.value" label="English" v-for="l in LanguageManager.supportedLanguages">
|
<a-select-option :value="l.value" label="English" v-for="l in LanguageManager.supportedLanguages">
|
||||||
<span role="img" aria-label="l.name" v-text="l.icon"></span>
|
<span role="img" aria-label="l.name" v-text="l.icon"></span>
|
||||||
<span v-text="l.name"></span>
|
<span v-text="l.name"></span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-button shape="circle" icon="setting"></a-button>
|
<a-button shape="circle" icon="setting"></a-button>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</div>
|
</div>
|
||||||
<a-row type="flex" justify="center">
|
<a-row type="flex" justify="center">
|
||||||
<a-col :style="{ width: '100%' }">
|
<a-col :style="{ width: '100%' }">
|
||||||
<h2 class="title headline zoom">
|
<h2 class="title headline zoom">
|
||||||
<span class="words-wrapper">
|
<span class="words-wrapper">
|
||||||
<b class="is-visible">{{ i18n "pages.login.hello" }}</b>
|
<b class="is-visible">{{ i18n "pages.login.hello" }}</b>
|
||||||
<b>{{ i18n "pages.login.title" }}</b>
|
<b>{{ i18n "pages.login.title" }}</b>
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row type="flex" justify="center">
|
<a-row type="flex" justify="center">
|
||||||
<a-col span="24">
|
<a-col span="24">
|
||||||
<a-form>
|
<a-form>
|
||||||
<a-space direction="vertical" size="middle">
|
<a-space direction="vertical" size="middle">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
||||||
placeholder='{{ i18n "username" }}' @keydown.enter.native="login" autofocus>
|
placeholder='{{ i18n "username" }}' @keydown.enter.native="login" autofocus>
|
||||||
<a-icon slot="prefix" type="user" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="user" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input-password autocomplete="password" name="password" v-model.trim="user.password"
|
<a-input-password autocomplete="password" name="password" v-model.trim="user.password"
|
||||||
placeholder='{{ i18n "password" }}' @keydown.enter.native="login">
|
placeholder='{{ i18n "password" }}' @keydown.enter.native="login">
|
||||||
<a-icon slot="prefix" type="lock" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="lock" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input-password>
|
</a-input-password>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="twoFactorEnable">
|
<a-form-item v-if="twoFactorEnable">
|
||||||
<a-input autocomplete="totp" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
<a-input autocomplete="totp" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
||||||
placeholder='{{ i18n "twoFactorCode" }}' @keydown.enter.native="login">
|
placeholder='{{ i18n "twoFactorCode" }}' @keydown.enter.native="login">
|
||||||
<a-icon slot="prefix" type="key" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="key" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-row justify="center" class="centered">
|
<a-row justify="center" class="centered">
|
||||||
<div :style="{ height: '50px', marginTop: '1rem', ...loading ? { width: '52px' } : { display: 'inline-block' } }" class="wave-btn-bg wave-btn-bg-cl">
|
<div :style="{ height: '50px', marginTop: '1rem', ...loading ? { width: '52px' } : { display: 'inline-block' } }" class="wave-btn-bg wave-btn-bg-cl">
|
||||||
<a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login"
|
<a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login"
|
||||||
:icon="loading ? 'poweroff' : undefined">
|
:icon="loading ? 'poweroff' : undefined">
|
||||||
[[ loading ? '' : '{{ i18n "login" }}' ]]
|
[[ loading ? '' : '{{ i18n "login" }}' ]]
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</transition>
|
</transition>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
{{template "page/body_scripts" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
<script>
|
<script>
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
loading: false,
|
loading: false,
|
||||||
user: {
|
user: {
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
twoFactorCode: ""
|
twoFactorCode: ""
|
||||||
},
|
|
||||||
twoFactorEnable: false,
|
|
||||||
lang: ""
|
|
||||||
},
|
},
|
||||||
async mounted() {
|
twoFactorEnable: false,
|
||||||
this.lang = LanguageManager.getLanguage();
|
lang: ""
|
||||||
this.twoFactorEnable = await this.getTwoFactorEnable();
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.lang = LanguageManager.getLanguage();
|
||||||
|
this.twoFactorEnable = await this.getTwoFactorEnable();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async login() {
|
||||||
|
this.loading = true;
|
||||||
|
const msg = await HttpUtil.post('/login', this.user);
|
||||||
|
this.loading = false;
|
||||||
|
if (msg.success) {
|
||||||
|
location.href = basePath + 'panel/';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
async getTwoFactorEnable() {
|
||||||
async login() {
|
this.loading = true;
|
||||||
this.loading = true;
|
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
||||||
const msg = await HttpUtil.post('/login', this.user);
|
this.loading = false;
|
||||||
this.loading = false;
|
if (msg.success) {
|
||||||
if (msg.success) {
|
this.twoFactorEnable = msg.obj;
|
||||||
location.href = basePath + 'panel/';
|
return msg.obj;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
async getTwoFactorEnable() {
|
|
||||||
this.loading = true;
|
|
||||||
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
|
||||||
this.loading = false;
|
|
||||||
if (msg.success) {
|
|
||||||
this.twoFactorEnable = msg.obj;
|
|
||||||
return msg.obj;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
var animationDelay = 2000;
|
var animationDelay = 2000;
|
||||||
initHeadline();
|
initHeadline();
|
||||||
|
|
||||||
function initHeadline() {
|
function initHeadline() {
|
||||||
animateHeadline(document.querySelectorAll('.headline'));
|
animateHeadline(document.querySelectorAll('.headline'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function animateHeadline(headlines) {
|
function animateHeadline(headlines) {
|
||||||
var duration = animationDelay;
|
var duration = animationDelay;
|
||||||
headlines.forEach(function (headline) {
|
headlines.forEach(function (headline) {
|
||||||
setTimeout(function () {
|
|
||||||
hideWord(headline.querySelector('.is-visible'));
|
|
||||||
}, duration);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideWord(word) {
|
|
||||||
var nextWord = takeNext(word);
|
|
||||||
switchWord(word, nextWord);
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
hideWord(nextWord);
|
hideWord(headline.querySelector('.is-visible'));
|
||||||
}, animationDelay);
|
}, duration);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function takeNext(word) {
|
function hideWord(word) {
|
||||||
return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild;
|
var nextWord = takeNext(word);
|
||||||
}
|
switchWord(word, nextWord);
|
||||||
|
setTimeout(function () {
|
||||||
|
hideWord(nextWord);
|
||||||
|
}, animationDelay);
|
||||||
|
}
|
||||||
|
|
||||||
function switchWord(oldWord, newWord) {
|
function takeNext(word) {
|
||||||
oldWord.classList.remove('is-visible');
|
return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild;
|
||||||
oldWord.classList.add('is-hidden');
|
}
|
||||||
newWord.classList.remove('is-hidden');
|
|
||||||
newWord.classList.add('is-visible');
|
function switchWord(oldWord, newWord) {
|
||||||
}
|
oldWord.classList.remove('is-visible');
|
||||||
});
|
oldWord.classList.add('is-hidden');
|
||||||
</script>
|
newWord.classList.remove('is-hidden');
|
||||||
</body>
|
newWord.classList.add('is-visible');
|
||||||
</html>
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{ template "page/body_end" .}}
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
|
@ -60,68 +58,70 @@
|
||||||
margin-block-end: 12px;
|
margin-block-end: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<body>
|
{{ template "page/head_end" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
|
||||||
<a-sidebar></a-sidebar>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="content-layout">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-layout-content>
|
<a-sidebar></a-sidebar>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-layout id="content-layout">
|
||||||
<transition name="list" appear>
|
<a-layout-content>
|
||||||
<a-alert type="error" v-if="confAlerts.length>0" :style="{ marginBottom: '10px' }"
|
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
<transition name="list" appear>
|
||||||
color="red"
|
<a-alert type="error" v-if="confAlerts.length>0" :style="{ marginBottom: '10px' }"
|
||||||
show-icon closable>
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
<template slot="description">
|
color="red"
|
||||||
<b>{{ i18n "secAlertConf" }}</b>
|
show-icon closable>
|
||||||
<ul><li v-for="a in confAlerts">[[ a ]]</li></ul>
|
<template slot="description">
|
||||||
</template>
|
<b>{{ i18n "secAlertConf" }}</b>
|
||||||
</a-alert>
|
<ul><li v-for="a in confAlerts">[[ a ]]</li></ul>
|
||||||
</transition>
|
</template>
|
||||||
<a-space direction="vertical">
|
</a-alert>
|
||||||
<a-card hoverable :style="{ marginBottom: '.5rem', overflowX: 'hidden' }">
|
</transition>
|
||||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
<a-space direction="vertical">
|
||||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
<a-card hoverable :style="{ marginBottom: '.5rem', overflowX: 'hidden' }">
|
||||||
<a-space direction="horizontal">
|
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||||
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.settings.save" }}</a-button>
|
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||||
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button>
|
<a-space direction="horizontal">
|
||||||
</a-space>
|
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.settings.save" }}</a-button>
|
||||||
</a-col>
|
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button>
|
||||||
<a-col :xs="24" :sm="14">
|
</a-space>
|
||||||
<template>
|
</a-col>
|
||||||
<div>
|
<a-col :xs="24" :sm="14">
|
||||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
<template>
|
||||||
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }"
|
<div>
|
||||||
message='{{ i18n "pages.settings.infoDesc" }}'
|
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
||||||
show-icon>
|
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }"
|
||||||
</a-alert>
|
message='{{ i18n "pages.settings.infoDesc" }}'
|
||||||
</div>
|
show-icon>
|
||||||
</template>
|
</a-alert>
|
||||||
</a-col>
|
</div>
|
||||||
</a-row>
|
</template>
|
||||||
</a-card>
|
</a-col>
|
||||||
<a-tabs default-active-key="1">
|
</a-row>
|
||||||
<a-tab-pane key="1" tab='{{ i18n "pages.settings.panelSettings" }}' :style="{ paddingTop: '20px' }">
|
</a-card>
|
||||||
{{ template "settings/panel/general" . }}
|
<a-tabs default-active-key="1">
|
||||||
</a-tab-pane>
|
<a-tab-pane key="1" tab='{{ i18n "pages.settings.panelSettings" }}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="2" tab='{{ i18n "pages.settings.securitySettings" }}' :style="{ paddingTop: '20px' }">
|
{{ template "settings/panel/general" . }}
|
||||||
{{ template "settings/panel/security" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="2" tab='{{ i18n "pages.settings.securitySettings" }}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="3" tab='{{ i18n "pages.settings.TGBotSettings" }}' :style="{ paddingTop: '20px' }">
|
{{ template "settings/panel/security" . }}
|
||||||
{{ template "settings/panel/telegram" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="3" tab='{{ i18n "pages.settings.TGBotSettings" }}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="4" tab='{{ i18n "pages.settings.subSettings" }}' :style="{ paddingTop: '20px' }">
|
{{ template "settings/panel/telegram" . }}
|
||||||
{{ template "settings/panel/subscription/general" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="4" tab='{{ i18n "pages.settings.subSettings" }}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="5" tab='{{ i18n "pages.settings.subSettings" }} Json' v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
{{ template "settings/panel/subscription/general" . }}
|
||||||
{{ template "settings/panel/subscription/json" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="5" tab='{{ i18n "pages.settings.subSettings" }} Json' v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
||||||
</a-tabs>
|
{{ template "settings/panel/subscription/json" . }}
|
||||||
</a-space>
|
</a-tab-pane>
|
||||||
</a-spin>
|
</a-tabs>
|
||||||
</a-layout-content>
|
</a-space>
|
||||||
</a-layout>
|
</a-spin>
|
||||||
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
</a-layout>
|
||||||
|
{{template "page/body_scripts" .}}
|
||||||
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/otpauth/otpauth.umd.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/otpauth/otpauth.umd.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/js/model/setting.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/setting.js?{{ .cur_ver }}"></script>
|
||||||
|
@ -531,5 +531,4 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
{{ template "page/body_end" .}}
|
||||||
</html>
|
|
|
@ -1,22 +1,8 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/codemirror.min.css?{{ .cur_ver }}">
|
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/codemirror.min.css?{{ .cur_ver }}">
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/fold/foldgutter.css">
|
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/fold/foldgutter.css">
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/xq.min.css?{{ .cur_ver }}">
|
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/xq.min.css?{{ .cur_ver }}">
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/lint/lint.css">
|
<link rel="stylesheet" href="{{ .base_path }}assets/codemirror/lint/lint.css">
|
||||||
|
|
||||||
<script src="{{ .base_path }}assets/js/model/outbound.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/codemirror.min.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/javascript.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/jshint.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/jsonlint.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/lint/lint.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/lint/javascript-lint.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/hint/javascript-hint.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/fold/foldcode.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/fold/foldgutter.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/codemirror/fold/brace-fold.js"></script>
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
|
@ -46,79 +32,92 @@
|
||||||
margin-block-end: 12px;
|
margin-block-end: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<body>
|
{{ template "page/head_end" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
|
||||||
<a-sidebar></a-sidebar>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="content-layout">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-layout-content>
|
<a-sidebar></a-sidebar>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-layout id="content-layout">
|
||||||
<transition name="list" appear>
|
<a-layout-content>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
<transition name="list" appear>
|
||||||
color="red"
|
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
show-icon closable>
|
color="red"
|
||||||
</a-alert>
|
description='{{ i18n "secAlertSsl" }}'
|
||||||
</transition>
|
show-icon closable>
|
||||||
<a-space direction="vertical">
|
</a-alert>
|
||||||
<a-card hoverable :style="{ marginBottom: '.5rem' }">
|
</transition>
|
||||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
<a-space direction="vertical">
|
||||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
<a-card hoverable :style="{ marginBottom: '.5rem' }">
|
||||||
<a-space direction="horizontal">
|
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||||
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">{{ i18n "pages.xray.save" }}</a-button>
|
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||||
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">{{ i18n "pages.xray.restart" }}</a-button>
|
<a-space direction="horizontal">
|
||||||
<a-popover v-if="restartResult"
|
<a-button type="primary" :disabled="saveBtnDisable" @click="updateXraySetting">{{ i18n "pages.xray.save" }}</a-button>
|
||||||
:overlay-class-name="themeSwitcher.currentTheme">
|
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartXray">{{ i18n "pages.xray.restart" }}</a-button>
|
||||||
<span slot="title">{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
<a-popover v-if="restartResult"
|
||||||
<template slot="content">
|
:overlay-class-name="themeSwitcher.currentTheme">
|
||||||
<span :style="{ maxWidth: '400px' }" v-for="line in restartResult.split('\n')">[[ line ]]</span>
|
<span slot="title">{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
||||||
</template>
|
<template slot="content">
|
||||||
<a-icon type="question-circle"></a-icon>
|
<span :style="{ maxWidth: '400px' }" v-for="line in restartResult.split('\n')">[[ line ]]</span>
|
||||||
</a-popover>
|
</template>
|
||||||
</a-space>
|
<a-icon type="question-circle"></a-icon>
|
||||||
</a-col>
|
</a-popover>
|
||||||
<a-col :xs="24" :sm="14">
|
</a-space>
|
||||||
<template>
|
</a-col>
|
||||||
<div>
|
<a-col :xs="24" :sm="14">
|
||||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
<template>
|
||||||
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }" message='{{ i18n "pages.settings.infoDesc" }}' show-icon>
|
<div>
|
||||||
</a-alert>
|
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
||||||
</div>
|
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }" message='{{ i18n "pages.settings.infoDesc" }}' show-icon>
|
||||||
</template>
|
</a-alert>
|
||||||
</a-col>
|
</div>
|
||||||
</a-row>
|
</template>
|
||||||
</a-card>
|
</a-col>
|
||||||
<a-tabs class="ant-card-dark-box-nohover" default-active-key="1"
|
</a-row>
|
||||||
@change="(activeKey) => { this.changePage(activeKey); }"
|
</a-card>
|
||||||
:class="themeSwitcher.currentTheme">
|
<a-tabs class="ant-card-dark-box-nohover" default-active-key="1"
|
||||||
<a-tab-pane key="tpl-basic" tab='{{ i18n "pages.xray.basicTemplate"}}' :style="{ paddingTop: '20px' }">
|
@change="(activeKey) => { this.changePage(activeKey); }"
|
||||||
{{ template "settings/xray/basics" . }}
|
:class="themeSwitcher.currentTheme">
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-basic" tab='{{ i18n "pages.xray.basicTemplate"}}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="tpl-routing" tab='{{ i18n "pages.xray.Routings"}}' :style="{ paddingTop: '20px' }">
|
{{ template "settings/xray/basics" . }}
|
||||||
{{ template "settings/xray/routing" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-routing" tab='{{ i18n "pages.xray.Routings"}}' :style="{ paddingTop: '20px' }">
|
||||||
<a-tab-pane key="tpl-outbound" tab='{{ i18n "pages.xray.Outbounds"}}' force-render="true">
|
{{ template "settings/xray/routing" . }}
|
||||||
{{ template "settings/xray/outbounds" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-outbound" tab='{{ i18n "pages.xray.Outbounds"}}' force-render="true">
|
||||||
<a-tab-pane key="tpl-reverse" tab='{{ i18n "pages.xray.outbound.reverse"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
{{ template "settings/xray/outbounds" . }}
|
||||||
{{ template "settings/xray/reverse" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-reverse" tab='{{ i18n "pages.xray.outbound.reverse"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
<a-tab-pane key="tpl-balancer" tab='{{ i18n "pages.xray.Balancers"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
{{ template "settings/xray/reverse" . }}
|
||||||
{{ template "settings/xray/balancers" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-balancer" tab='{{ i18n "pages.xray.Balancers"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
<a-tab-pane key="tpl-dns" tab='DNS' :style="{ paddingTop: '20px' }" force-render="true">
|
{{ template "settings/xray/balancers" . }}
|
||||||
{{ template "settings/xray/dns" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-dns" tab='DNS' :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
{{ template "settings/xray/dns" . }}
|
||||||
{{ template "settings/xray/advanced" . }}
|
</a-tab-pane>
|
||||||
</a-tab-pane>
|
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' :style="{ paddingTop: '20px' }" force-render="true">
|
||||||
</a-tabs>
|
{{ template "settings/xray/advanced" . }}
|
||||||
</a-space>
|
</a-tab-pane>
|
||||||
</a-spin>
|
</a-tabs>
|
||||||
</a-layout-content>
|
</a-space>
|
||||||
</a-layout>
|
</a-spin>
|
||||||
</a-layout>
|
</a-layout-content>
|
||||||
{{template "js" .}}
|
</a-layout>
|
||||||
|
</a-layout>
|
||||||
|
{{template "page/body_scripts" .}}
|
||||||
|
<script src="{{ .base_path }}assets/js/model/outbound.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/codemirror.min.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/javascript.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/jshint.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/jsonlint.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/lint/lint.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/lint/javascript-lint.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/hint/javascript-hint.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/fold/foldcode.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/fold/foldgutter.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/codemirror/fold/brace-fold.js"></script>
|
||||||
{{template "component/aSidebar" .}}
|
{{template "component/aSidebar" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
{{template "component/aTableSortable" .}}
|
{{template "component/aTableSortable" .}}
|
||||||
|
@ -1410,5 +1409,4 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
{{ template "page/body_end" .}}
|
||||||
</html>
|
|
Loading…
Reference in a new issue