Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShishkevich D. <135337715+shishkevichd@users.noreply.github.com>2025-06-21 11:38:43 +0300
committerGitHub <noreply@github.com>2025-06-21 11:38:43 +0300
commitd642774a4493912e76dbc294dce834cf5b635324 (patch)
tree98a761be40633469481ab2812a541c4ad8a742aa
parent1644904755983ae76fca5bc7466a5da530c37013 (diff)
refactor: use new page templates
-rw-r--r--web/html/common/head.html31
-rw-r--r--web/html/common/js.html14
-rw-r--r--web/html/common/page.html58
-rw-r--r--web/html/inbounds.html27
-rw-r--r--web/html/index.html744
-rw-r--r--web/html/login.html338
-rw-r--r--web/html/settings.html131
-rw-r--r--web/html/xray.html178
8 files changed, 762 insertions, 759 deletions
diff --git a/web/html/common/head.html b/web/html/common/head.html
deleted file mode 100644
index 35901769..00000000
--- a/web/html/common/head.html
+++ /dev/null
@@ -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}} \ No newline at end of file
diff --git a/web/html/common/js.html b/web/html/common/js.html
deleted file mode 100644
index 1c2d64b3..00000000
--- a/web/html/common/js.html
+++ /dev/null
@@ -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}} \ No newline at end of file
diff --git a/web/html/common/page.html b/web/html/common/page.html
new file mode 100644
index 00000000..f1c58fe1
--- /dev/null
+++ b/web/html/common/page.html
@@ -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 }} \ No newline at end of file
diff --git a/web/html/inbounds.html b/web/html/inbounds.html
index 5ee541df..7b00ae5e 100644
--- a/web/html/inbounds.html
+++ b/web/html/inbounds.html
@@ -1,6 +1,4 @@
-<!DOCTYPE html>
-<html lang="en">
-{{template "head" .}}
+{{ template "page/head_start" .}}
<style>
.ant-table:not(.ant-table-expanded-row .ant-table) {
outline: 1px solid #f0f0f0;
@@ -143,8 +141,9 @@
padding: 12px 2px;
}
</style>
+{{ template "page/head_end" .}}
-<body>
+{{ template "page/body_start" .}}
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
<a-sidebar></a-sidebar>
<a-layout id="content-layout">
@@ -657,7 +656,7 @@
</a-layout-content>
</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/uri/URI.min.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/aCustomStatistic" .}}
{{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>
const columns = [{
title: "ID",
@@ -1607,13 +1613,4 @@
},
});
</script>
-
-{{template "modals/inboundModal"}}
-{{template "modals/promptModal"}}
-{{template "modals/qrcodeModal"}}
-{{template "modals/textModal"}}
-{{template "modals/inboundInfoModal"}}
-{{template "modals/clientsModal"}}
-{{template "modals/clientsBulkModal"}}
-</body>
-</html>
+{{ template "page/body_end" .}} \ No newline at end of file
diff --git a/web/html/index.html b/web/html/index.html
index 2a6fb0ad..61e3947f 100644
--- a/web/html/index.html
+++ b/web/html/index.html
@@ -1,6 +1,4 @@
-<!DOCTYPE html>
-<html lang="en">
-{{template "head" .}}
+{{ template "page/head_start" .}}
<style>
@media (min-width: 769px) {
.ant-layout-content {
@@ -79,384 +77,385 @@
}
}
</style>
+{{ template "page/head_end" .}}
-<body>
- <a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
- <a-sidebar></a-sidebar>
- <a-layout id="content-layout">
- <a-layout-content>
- <a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
- <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>
- </transition>
- <transition name="list" appear>
- <template>
- <a-row v-if="!status.isLoaded">
- <a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
- <a-spin tip='{{ i18n "loading" }}'></a-spin>
+{{ template "page/body_start" .}}
+<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
+ <a-sidebar></a-sidebar>
+ <a-layout id="content-layout">
+ <a-layout-content>
+ <a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
+ <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>
+ </transition>
+ <transition name="list" appear>
+ <template>
+ <a-row v-if="!status.isLoaded">
+ <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-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-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-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 #extra>
- <template v-if="status.xray.state != 'error'">
- <a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
- </template>
- <template v-else>
- <a-popover :overlay-class-name="themeSwitcher.currentTheme">
- <span slot="title">
- <a-row type="flex" align="middle" justify="space-between">
- <a-col>
- <span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
- </a-col>
- <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>
+ <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 #extra>
+ <template v-if="status.xray.state != 'error'">
+ <a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
</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" }}' ]]
+ <template v-else>
+ <a-popover :overlay-class-name="themeSwitcher.currentTheme">
+ <span slot="title">
+ <a-row type="flex" align="middle" justify="space-between">
+ <a-col>
+ <span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
+ </a-col>
+ <a-col>
+ <a-icon type="bars" :style="{ cursor: 'pointer', float: 'right' }" @click="openLogs()"></a-tag>
+ </a-col>
+ </a-row>
</span>
- </a-space>
- </template>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='{{ i18n "menu.link" }}' hoverable>
- <template #actions>
- <a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
- <a-icon type="bars"></a-icon>
- <span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
- </a-space>
- <a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
- <a-icon type="control"></a-icon>
- <span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
- </a-space>
- <a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
- <a-icon type="cloud-server"></a-icon>
- <span v-if="!isMobile">{{ i18n "pages.index.backup" }}</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>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='3X-UI' hoverable>
- <a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank">
- <a-tag color="green">
- <span>v{{ .cur_ver }}</span>
- </a-tag>
- </a>
- <a rel="noopener" href="https://t.me/XrayUI" target="_blank">
- <a-tag color="green">
- <span>@XrayUI</span>
- </a-tag>
- </a>
- <a rel="noopener" href="https://github.com/MHSanaei/3x-ui/wiki" target="_blank">
- <a-tag>
- <span>{{ i18n "pages.index.documentation" }}</span>
- </a-tag>
- </a>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <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>
+ </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>
+ </a-space>
+ </template>
+ </a-card>
+ </a-col>
+ <a-col :sm="24" :lg="12">
+ <a-card title='{{ i18n "menu.link" }}' hoverable>
+ <template #actions>
+ <a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
+ <a-icon type="bars"></a-icon>
+ <span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
+ </a-space>
+ <a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
+ <a-icon type="control"></a-icon>
+ <span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
+ </a-space>
+ <a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
+ <a-icon type="cloud-server"></a-icon>
+ <span v-if="!isMobile">{{ i18n "pages.index.backup" }}</span>
+ </a-space>
+ </template>
+ </a-card>
+ </a-col>
+ <a-col :sm="24" :lg="12">
+ <a-card title='3X-UI' hoverable>
+ <a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank">
<a-tag color="green">
- <a-tooltip>
- [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
- <template slot="title">
- {{ i18n "pages.index.systemLoadDesc" }}
- </template>
- </a-tooltip>
+ <span>v{{ .cur_ver }}</span>
+ </a-tag>
+ </a>
+ <a rel="noopener" href="https://t.me/XrayUI" target="_blank">
+ <a-tag color="green">
+ <span>@XrayUI</span>
</a-tag>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='{{ i18n "usage"}}' hoverable>
- <a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
- <a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
- <a-row :gutter="isMobile ? [8,8] : 0">
- <a-col :span="12">
- <a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
- <template #prefix>
- <a-icon type="arrow-up" />
- </template>
- <template #suffix>
- /s
- </template>
- </a-custom-statistic>
- </a-col>
- <a-col :span="12">
- <a-custom-statistic title='{{ i18n "pages.index.download" }}' :value="SizeFormatter.sizeFormat(status.netIO.down)">
- <template #prefix>
- <a-icon type="arrow-down" />
- </template>
- <template #suffix>
- /s
- </template>
- </a-custom-statistic>
- </a-col>
- </a-row>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
- <a-row :gutter="isMobile ? [8,8] : 0">
- <a-col :span="12">
- <a-custom-statistic title='{{ i18n "pages.index.sent" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.sent)">
- <template #prefix>
- <a-icon type="cloud-upload" />
- </template>
- </a-custom-statistic>
- </a-col>
- <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" }}
+ </a>
+ <a rel="noopener" href="https://github.com/MHSanaei/3x-ui/wiki" target="_blank">
+ <a-tag color="purple">
+ <span>{{ i18n "pages.index.documentation" }}</span>
+ </a-tag>
+ </a>
+ </a-card>
+ </a-col>
+ <a-col :sm="24" :lg="12">
+ <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-tooltip>
+ [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
+ <template slot="title">
+ {{ i18n "pages.index.systemLoadDesc" }}
+ </template>
+ </a-tooltip>
+ </a-tag>
+ </a-card>
+ </a-col>
+ <a-col :sm="24" :lg="12">
+ <a-card title='{{ i18n "usage"}}' hoverable>
+ <a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
+ <a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
+ </a-card>
+ </a-col>
+ <a-col :sm="24" :lg="12">
+ <a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
+ <a-row :gutter="isMobile ? [8,8] : 0">
+ <a-col :span="12">
+ <a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
+ <template #prefix>
+ <a-icon type="arrow-up" />
</template>
- <a-icon :type="showIp ? 'eye' : 'eye-invisible'" :style="{ fontSize: '1rem' }" @click="showIp = !showIp"></a-icon>
- </a-tooltip>
- </template>
- <a-row :class="showIp ? 'ip-visible' : 'ip-hidden'" :gutter="isMobile ? [8,8] : 0">
- <a-col :span="isMobile ? 24 : 12">
- <a-custom-statistic title="IPv4" :value="status.publicIP.ipv4">
- <template #prefix>
- <a-icon type="global" />
- </template>
- </a-custom-statistic>
- </a-col>
- <a-col :span="isMobile ? 24 : 12">
- <a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
- <template #prefix>
- <a-icon type="global" />
- </template>
- </a-custom-statistic>
- </a-col>
- </a-row>
- </a-card>
- </a-col>
- <a-col :sm="24" :lg="12">
- <a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
- <a-row :gutter="isMobile ? [8,8] : 0">
- <a-col :span="12">
- <a-custom-statistic title="TCP" :value="status.tcpCount">
- <template #prefix>
- <a-icon type="swap" />
- </template>
- </a-custom-statistic>
- </a-col>
- <a-col :span="12">
- <a-custom-statistic title="UDP" :value="status.udpCount">
- <template #prefix>
- <a-icon type="swap" />
- </template>
- </a-custom-statistic>
- </a-col>
- </a-row>
- </a-card>
- </a-col>
- </a-row>
- </template>
- </transition>
- </a-spin>
- </a-layout-content>
- </a-layout>
- <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">