|
@@ -84,7 +84,7 @@
|
|
|
<a-layout-content>
|
|
|
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
|
|
<transition name="list" appear>
|
|
|
- <a-alert type="error" v-if="showAlert" style="margin-bottom: 10px"
|
|
|
+ <a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
|
|
message='{{ i18n "secAlertTitle" }}'
|
|
|
color="red"
|
|
|
description='{{ i18n "secAlertSsl" }}'
|
|
@@ -94,8 +94,8 @@
|
|
|
<transition name="list" appear>
|
|
|
<template>
|
|
|
<a-row v-if="!status.isLoaded">
|
|
|
- <a-card hoverable style="text-align: center; padding: 30px 0; margin-top: 10px; background: transparent;">
|
|
|
- <a-spin tip="Loading..."></a-spin>
|
|
|
+ <a-card hoverable :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent' }">
|
|
|
+ <a-spin tip='{{ i18n "loading" }}'></a-spin>
|
|
|
</a-card>
|
|
|
</a-row>
|
|
|
<a-row v-else>
|
|
@@ -104,19 +104,22 @@
|
|
|
<a-row>
|
|
|
<a-col :sm="24" :md="12">
|
|
|
<a-row>
|
|
|
- <a-col :span="12" style="text-align: center">
|
|
|
+ <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>CPU:</b> [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]] <a-tooltip>
|
|
|
- <a-icon type="area-chart"></a-icon>
|
|
|
- <template slot="title">
|
|
|
- <div><b>Logical Processors:</b> [[ (status.logicalPro) ]]</div>
|
|
|
- <div><b>Speed:</b> [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
|
|
- </template>
|
|
|
- </a-tooltip></div>
|
|
|
+ <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="text-align: center">
|
|
|
+ <a-col :span="12" :style="{ textAlign: 'center' }">
|
|
|
<a-progress type="dashboard" status="normal"
|
|
|
:stroke-color="status.mem.color"
|
|
|
:percent="status.mem.percent"></a-progress>
|
|
@@ -128,20 +131,20 @@
|
|
|
</a-col>
|
|
|
<a-col :sm="24" :md="12">
|
|
|
<a-row>
|
|
|
- <a-col :span="12" style="text-align: center">
|
|
|
+ <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>Swap:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
|
|
+ <b>{{ i18n "pages.index.swap" }}:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
|
|
</div>
|
|
|
</a-col>
|
|
|
- <a-col :span="12" style="text-align: center">
|
|
|
+ <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.hard"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
|
|
+ <b>{{ i18n "pages.index.storage"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
|
|
</div>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
@@ -160,31 +163,38 @@
|
|
|
</a-space>
|
|
|
</template>
|
|
|
<template #extra>
|
|
|
- <template v-if="status.xray.state != State.Error">
|
|
|
- <a-badge status="processing" class="running-animation" :text="status.xray.state" :color="status.xray.color" style="text-transform: capitalize;"/>
|
|
|
+ <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" style="font-size: 12pt">An error occurred while running Xray
|
|
|
- <a-tag color="purple" style="cursor: pointer; float: right;" @click="openLogs()">{{ i18n "pages.index.logs" }}</a-tag>
|
|
|
+ <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">
|
|
|
- <p style="max-width: 400px" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</p>
|
|
|
+ <span :style="{ maxWidth: '400px' }" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</span>
|
|
|
</template>
|
|
|
- <a-badge :text="status.xray.state" :color="status.xray.color" style="text-transform: capitalize;"/>
|
|
|
+ <a-badge :text="status.xray.stateMsg" :color="status.xray.color"/>
|
|
|
</a-popover>
|
|
|
</template>
|
|
|
</template>
|
|
|
<template #actions>
|
|
|
- <a-space direction="horizontal" @click="stopXrayService" style="justify-content: center;">
|
|
|
+ <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="justify-content: center;">
|
|
|
+ <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="justify-content: center;">
|
|
|
+ <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" }}' ]]
|
|
@@ -196,15 +206,15 @@
|
|
|
<a-col :sm="24" :lg="12">
|
|
|
<a-card title='{{ i18n "menu.link" }}' hoverable>
|
|
|
<template #actions>
|
|
|
- <a-space direction="horizontal" @click="openLogs()" style="justify-content: center;">
|
|
|
+ <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="justify-content: center;">
|
|
|
+ <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="justify-content: center;">
|
|
|
+ <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>
|
|
@@ -237,13 +247,13 @@
|
|
|
</a-col>
|
|
|
<a-col :sm="24" :lg="12">
|
|
|
<a-card title='{{ i18n "usage"}}' hoverable>
|
|
|
- <a-tag color="green"> RAM: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
|
|
|
- <a-tag color="green"> Threads: [[ status.appStats.threads ]] </a-tag>
|
|
|
+ <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>
|
|
|
+ <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>
|
|
@@ -269,7 +279,7 @@
|
|
|
</a-col>
|
|
|
<a-col :sm="24" :lg="12">
|
|
|
<a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
|
|
|
- <a-row>
|
|
|
+ <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>
|
|
@@ -297,15 +307,15 @@
|
|
|
<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'">
|
|
|
- <a-col :xs="24" :xxl="12" :style="{ marginTop: isMobile ? '10px' : 0 }">
|
|
|
+ <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 :xs="24" :xxl="12" :style="{ marginTop: isMobile ? '10px' : 0 }">
|
|
|
+ <a-col :span="isMobile ? 24 : 12">
|
|
|
<a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
|
|
|
<template #prefix>
|
|
|
<a-icon type="global" />
|
|
@@ -317,7 +327,7 @@
|
|
|
</a-col>
|
|
|
<a-col :sm="24" :lg="12">
|
|
|
<a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
|
|
|
- <a-row>
|
|
|
+ <a-row :gutter="isMobile ? [8,8] : 0">
|
|
|
<a-col :span="12">
|
|
|
<a-custom-statistic title="TCP" :value="status.tcpCount">
|
|
|
<template #prefix>
|
|
@@ -343,9 +353,9 @@
|
|
|
</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-alert type="warning" style="margin-bottom: 12px; width: 100%;"
|
|
|
+ <a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }"
|
|
|
message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
|
|
- <a-list class="ant-xray-version-list" bordered style="width: 100%;">
|
|
|
+ <a-list class="ant-xray-version-list" bordered :style="{ width: '100%' }">
|
|
|
<a-list-item class="ant-xray-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>
|
|
@@ -360,15 +370,15 @@
|
|
|
{{ i18n "pages.index.logs" }}
|
|
|
<a-icon :spin="logModal.loading"
|
|
|
type="sync"
|
|
|
- style="vertical-align: middle; margin-left: 10px;"
|
|
|
+ :style="{ verticalAlign: 'middle', marginLeft: '10px' }"
|
|
|
:disabled="logModal.loading"
|
|
|
@click="openLogs()">
|
|
|
</a-icon>
|
|
|
</template>
|
|
|
<a-form layout="inline">
|
|
|
- <a-form-item style="margin-right: 0.5rem;">
|
|
|
+ <a-form-item :style="{ marginRight: '0.5rem' }">
|
|
|
<a-input-group compact>
|
|
|
- <a-select size="small" v-model="logModal.rows" style="width:70px;"
|
|
|
+ <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>
|
|
@@ -376,7 +386,7 @@
|
|
|
<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;"
|
|
|
+ <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>
|
|
@@ -389,13 +399,13 @@
|
|
|
<a-form-item>
|
|
|
<a-checkbox v-model="logModal.syslog" @change="openLogs()">SysLog</a-checkbox>
|
|
|
</a-form-item>
|
|
|
- <a-form-item style="float: right;">
|
|
|
+ <a-form-item :style="{ float: 'right' }">
|
|
|
<a-button type="primary" icon="download"
|
|
|
:href="'data:application/text;charset=utf-8,' + encodeURIComponent(logModal.logs?.join('\n'))" download="x-ui.log">
|
|
|
</a-button>
|
|
|
</a-form-item>
|
|
|
</a-form>
|
|
|
- <div class="ant-input" style="height: auto; max-height: 500px; overflow: auto; margin-top: 0.5rem;" v-html="logModal.formattedLogs"></div>
|
|
|
+ <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"
|
|
@@ -403,7 +413,7 @@
|
|
|
:closable="true"
|
|
|
footer=""
|
|
|
:class="themeSwitcher.currentTheme">
|
|
|
- <a-list class="ant-backup-list" bordered style="width: 100%;">
|
|
|
+ <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>
|
|
@@ -427,13 +437,6 @@
|
|
|
{{template "component/aCustomStatistic" .}}
|
|
|
{{template "modals/textModal"}}
|
|
|
<script>
|
|
|
- const State = {
|
|
|
- Running: "running",
|
|
|
- Stop: "stop",
|
|
|
- Error: "error",
|
|
|
- }
|
|
|
- Object.freeze(State);
|
|
|
-
|
|
|
class CurTotal {
|
|
|
|
|
|
constructor(current, total) {
|
|
@@ -478,7 +481,8 @@
|
|
|
this.uptime = 0;
|
|
|
this.appUptime = 0;
|
|
|
this.appStats = {threads: 0, mem: 0, uptime: 0};
|
|
|
- this.xray = { state: State.Stop, errorMsg: "", version: "", color: "" };
|
|
|
+
|
|
|
+ this.xray = { state: 'stop', stateMsg: "", errorMsg: "", version: "", color: "" };
|
|
|
|
|
|
if (data == null) {
|
|
|
return;
|
|
@@ -503,17 +507,22 @@
|
|
|
this.appStats = data.appStats;
|
|
|
this.xray = data.xray;
|
|
|
switch (this.xray.state) {
|
|
|
- case State.Running:
|
|
|
+ case 'running':
|
|
|
this.xray.color = "green";
|
|
|
+ this.xray.stateMsg = '{{ i18n "pages.index.xrayStatusRunning" }}';
|
|
|
break;
|
|
|
- case State.Stop:
|
|
|
+ case 'stop':
|
|
|
this.xray.color = "orange";
|
|
|
+ this.xray.stateMsg = '{{ i18n "pages.index.xrayStatusStop" }}';
|
|
|
break;
|
|
|
- case State.Error:
|
|
|
+ case 'error':
|
|
|
this.xray.color = "red";
|
|
|
+ this.xray.stateMsg ='{{ i18n "pages.index.xrayStatusError" }}';
|
|
|
break;
|
|
|
default:
|
|
|
this.xray.color = "gray";
|
|
|
+ this.xray.stateMsg = '{{ i18n "pages.index.xrayStatusUnknown" }}';
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -596,6 +605,7 @@
|
|
|
const app = new Vue({
|
|
|
delimiters: ['[[', ']]'],
|
|
|
el: '#app',
|
|
|
+ mixins: [MediaQueryMixin],
|
|
|
data: {
|
|
|
themeSwitcher,
|
|
|
status: new Status(),
|
|
@@ -605,8 +615,7 @@
|
|
|
spinning: false,
|
|
|
loadingTip: '{{ i18n "loading"}}',
|
|
|
showAlert: false,
|
|
|
- showIp: false,
|
|
|
- isMobile: DeviceUtils.isMobile()
|
|
|
+ showIp: false
|
|
|
},
|
|
|
methods: {
|
|
|
loading(spinning, tip = '{{ i18n "loading"}}') {
|