[darkmode] re-design theme-switch

Co-authored-by: Hamidreza Ghavami <hamid.r.gh.1998@gmail.com>
This commit is contained in:
Alireza Ahmadi
2023-05-15 15:24:08 +02:00
parent 14270caa16
commit abc82cef4c
20 changed files with 190 additions and 146 deletions

View File

@@ -1,7 +1,7 @@
{{define "promptModal"}}
<a-modal id="prompt-modal" v-model="promptModal.visible" :title="promptModal.title"
:closable="true" @ok="promptModal.ok" :mask-closable="false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:ok-text="promptModal.okText" cancel-text='{{ i18n "cancel" }}'>
<a-input id="prompt-modal-input" :type="promptModal.type"
v-model="promptModal.value"

View File

@@ -1,7 +1,7 @@
{{define "qrcodeModal"}}
<a-modal id="qrcode-modal" v-model="qrModal.visible" :title="qrModal.title"
:closable="true"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:footer="null"
width="300px">
<a-tag color="green" style="margin-bottom: 10px;display: block;text-align: center;" >{{ i18n "pages.inbounds.clickOnQRcode" }}</a-tag>

View File

@@ -1,7 +1,7 @@
{{define "textModal"}}
<a-modal id="text-modal" v-model="txtModal.visible" :title="txtModal.title"
:closable="true" ok-text='{{ i18n "copy" }}' cancel-text='{{ i18n "close" }}'
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:ok-button-props="{attrs:{id:'txt-modal-ok-btn'}}">
<a-button v-if="!ObjectUtil.isEmpty(txtModal.fileName)" type="primary" style="margin-bottom: 10px;"
:href="'data:application/text;charset=utf-8,' + encodeURIComponent(txtModal.content)"

View File

@@ -9,7 +9,6 @@
h1 {
text-align: center;
color: #fff;
margin: 20px 0 50px 0;
}
@@ -18,6 +17,12 @@
border-radius: 30px;
}
.ant-input-group-addon {
border-radius: 0 30px 30px 0;
width: 50px;
font-size: 18px;
}
.ant-input-affix-wrapper .ant-input-prefix {
left: 23px;
}
@@ -26,20 +31,26 @@
padding-left: 50px;
}
.selectLang{
.centered {
display: flex;
text-align: center;
align-items: center;
justify-content: center;
}
.title {
font-size: 32px;
font-weight: bold;
}
</style>
<body>
<a-layout id="app" v-cloak>
<a-layout id="app" v-cloak :class="themeSwitcher.darkClass">
<transition name="list" appear>
<a-layout-content>
<a-row type="flex" justify="center">
<a-col :xs="22" :sm="20" :md="16" :lg="12" :xl="8">
<h1>{{ i18n "pages.login.title" }}</h1>
<h1 :style="themeSwitcher.textStyle">{{ i18n "pages.login.title" }}</h1>
</a-col>
</a-row>
<a-row type="flex" justify="center">
@@ -48,40 +59,39 @@
<a-form-item>
<a-input v-model.trim="user.username" placeholder='{{ i18n "username" }}'
@keydown.enter.native="login" autofocus>
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/>
<a-icon slot="prefix" type="user" :style="'font-size: 16px;' + themeSwitcher.textStyle"/>
</a-input>
</a-form-item>
<a-form-item>
<a-input type="password" v-model.trim="user.password"
placeholder='{{ i18n "password" }}' @keydown.enter.native="login">
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/>
<a-icon slot="prefix" type="lock" :style="themeSwitcher.textStyle"/>
</a-input>
</a-form-item>
<a-form-item>
<a-button block @click="login" :loading="loading">{{ i18n "login" }}</a-button>
<a-row justify="center" class="centered">
<a-button type="primary" :loading="loading" @click="login" :icon="loading ? 'poweroff' : undefined"
:style="loading ? { width: '50px' } : { display: 'block', width: '100%' }">
[[ loading ? '' : '{{ i18n "login" }}' ]]
</a-button>
</a-row>
</a-form-item>
<a-form-item>
<a-row justify="center" class="selectLang">
<a-col :span="4"><span>Language : </span></a-col>
<a-col :span="6">
<a-select
ref="selectLang"
v-model="lang"
@change="setLang(lang)"
>
<a-select-option :value="l.value" label="China" v-for="l in supportLangs" >
<a-row justify="center" class="centered">
<a-col :span="12">
<a-select ref="selectLang" v-model="lang" @change="setLang(lang)" :dropdown-class-name="themeSwitcher.darkCardClass">
<a-select-option :value="l.value" label="English" v-for="l in supportLangs">
<span role="img" aria-label="l.name" v-text="l.icon"></span>
&nbsp;&nbsp;<span v-text="l.name"></span>
</a-select-option>
</a-select>
</a-col>
</a-row>
</a-form-item>
<a-form-item>
<a-row justify="center" class="centered">
<theme-switch />
</a-row>
</a-form-item>
</a-form>
</a-col>
@@ -90,22 +100,20 @@
</transition>
</a-layout>
{{template "js" .}}
{{template "component/themeSwitcher" .}}
<script>
const leftColor = RandomUtil.randomIntRange(0x222222, 0xFFFFFF / 2).toString(16);
const rightColor = RandomUtil.randomIntRange(0xFFFFFF / 2, 0xDDDDDD).toString(16);
const deg = RandomUtil.randomIntRange(0, 360);
const background = `linear-gradient(${deg}deg, #${leftColor} 10%, #${rightColor} 100%)`;
document.querySelector('#app').style.background = background;
const app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
themeSwitcher,
loading: false,
user: new User(),
lang : ""
lang: ""
},
created(){
this.lang = getLang();
created() {
this.updateBackground();
this.lang = getLang();
},
methods: {
async login() {
@@ -115,8 +123,16 @@
if (msg.success) {
location.href = basePath + 'xui/';
}
}
}
},
updateBackground() {
document.querySelector('#app').style.background = this.themeSwitcher.isDarkTheme ? colors.dark.bg : 'white';
},
},
watch: {
'themeSwitcher.isDarkTheme'(newVal, oldVal) {
this.updateBackground();
},
},
});
</script>
</body>

View File

@@ -1,7 +1,7 @@
{{define "clientsBulkModal"}}
<a-modal id="client-bulk-modal" v-model="clientsBulkModal.visible" :title="clientsBulkModal.title" @ok="clientsBulkModal.ok"
:confirm-loading="clientsBulkModal.confirmLoading" :closable="true" :mask-closable="false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:ok-text="clientsBulkModal.okText" cancel-text='{{ i18n "close" }}'>
<a-form layout="inline">
<table width="100%" class="ant-table-tbody">
@@ -89,7 +89,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -121,7 +121,7 @@
</tr>
<tr v-else>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -1,7 +1,7 @@
{{define "clientsModal"}}
<a-modal id="client-modal" v-model="clientModal.visible" :title="clientModal.title" @ok="clientModal.ok"
:confirm-loading="clientModal.confirmLoading" :closable="true" :mask-closable="false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:ok-text="clientModal.okText" cancel-text='{{ i18n "close" }}'>
{{template "form/client"}}
</a-modal>
@@ -132,7 +132,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: async () => {

View File

@@ -11,10 +11,6 @@
<a-icon type="setting"></a-icon>
<span>{{ i18n "menu.setting"}}</span>
</a-menu-item>
<!--<a-menu-item key="{{ .base_path }}xui/clients">-->
<!-- <a-icon type="laptop"></a-icon>-->
<!-- <span>Client</span>-->
<!--</a-menu-item>-->
<a-sub-menu>
<template slot="title">
<a-icon type="link"></a-icon>
@@ -33,17 +29,14 @@
{{define "commonSider"}}
<a-layout-sider :theme="siderDrawer.theme" id="sider" collapsible breakpoint="md" collapsed-width="0">
<a-menu :theme="siderDrawer.theme" mode="inline" selected-keys="">
<a-layout-sider :theme="themeSwitcher.currentTheme" id="sider" collapsible breakpoint="md" collapsed-width="0">
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" selected-keys="">
<a-menu-item mode="inline">
<a-icon type="bg-colors"></a-icon>
<a-switch :default-checked="siderDrawer.isDarkTheme"
checked-children="☀"
un-checked-children="🌙"
@change="siderDrawer.changeTheme()"></a-switch>
<theme-switch />
</a-menu-item>
</a-menu>
<a-menu :theme="siderDrawer.theme" mode="inline" :selected-keys="['{{ .request_uri }}']"
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="['{{ .request_uri }}']"
@click="({key}) => key.startsWith('http') ? window.open(key) : location.href = key">
{{template "menuItems" .}}
</a-menu>
@@ -51,32 +44,25 @@
<a-drawer id="sider-drawer" placement="left" :closable="false"
@close="siderDrawer.close()"
:visible="siderDrawer.visible"
:wrap-class-name="siderDrawer.isDarkTheme ? 'ant-drawer-dark' : ''"
:wrap-class-name="themeSwitcher.darkDrawerClass"
:wrap-style="{ padding: 0 }">
<div class="drawer-handle" @click="siderDrawer.change()" slot="handle">
<a-icon :type="siderDrawer.visible ? 'close' : 'menu-fold'"></a-icon>
</div>
<a-menu :theme="siderDrawer.theme" mode="inline" selected-keys="">
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" selected-keys="">
<a-menu-item mode="inline">
<a-icon type="bg-colors"></a-icon>
<a-switch :default-checked="siderDrawer.isDarkTheme"
checked-children="☀"
un-checked-children="🌙"
@change="siderDrawer.changeTheme()"></a-switch>
<theme-switch />
</a-menu-item>
</a-menu>
<a-menu :theme="siderDrawer.theme" mode="inline" :selected-keys="['{{ .request_uri }}']"
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="['{{ .request_uri }}']"
@click="({key}) => key.startsWith('http') ? window.open(key) : location.href = key">
{{template "menuItems" .}}
</a-menu>
</a-drawer>
<script>
const darkClass = "ant-card-dark";
const bgDarkStyle = "background-color: #242c3a";
const siderDrawer = {
visible: false,
collapsed: false,
isDarkTheme: localStorage.getItem("dark-mode") === 'true' ? true : false,
show() {
this.visible = true;
},
@@ -85,16 +71,6 @@
},
change() {
this.visible = !this.visible;
},
toggleCollapsed() {
this.collapsed = !this.collapsed;
},
changeTheme() {
this.isDarkTheme = ! this.isDarkTheme;
localStorage.setItem("dark-mode", this.isDarkTheme);
},
get theme() {
return this.isDarkTheme ? 'dark' : 'light';
}
};

View File

@@ -0,0 +1,58 @@
{{define "component/themeSwitchTemplate"}}
<template>
<a-switch :default-checked="themeSwitcher.isDarkTheme"
checked-children="☀"
un-checked-children="🌙"
@change="themeSwitcher.toggleTheme()">
</a-switch>
</template>
{{end}}
{{define "component/themeSwitcher"}}
<script>
const colors = {
dark: {
bg: "#242c3a",
text: "hsla(0,0%,100%,.65)"
},
light: {
bg: '#f0f2f5',
text: "rgba(0, 0, 0, 0.7)",
}
}
function createThemeSwitcher() {
const isDarkTheme = localStorage.getItem('dark-mode') === 'true';
const theme = isDarkTheme ? 'dark' : 'light';
return {
isDarkTheme,
bgStyle: `background: ${colors[theme].bg};`,
textStyle: `color: ${colors[theme].text};`,
darkClass: isDarkTheme ? 'ant-card-dark' : '',
darkCardClass: isDarkTheme ? 'ant-card-dark' : '',
darkDrawerClass: isDarkTheme ? 'ant-drawer-dark' : '',
get currentTheme() {
return this.isDarkTheme ? 'dark' : 'light';
},
toggleTheme() {
this.isDarkTheme = !this.isDarkTheme;
this.theme = this.isDarkTheme ? 'dark' : 'light';
localStorage.setItem('dark-mode', this.isDarkTheme);
this.bgStyle = `background: ${colors[this.theme].bg};`;
this.textStyle = `color: ${colors[this.theme].text};`;
this.darkClass = this.isDarkTheme ? 'ant-card-dark' : '';
this.darkCardClass = this.isDarkTheme ? 'ant-card-dark' : '';
this.darkDrawerClass = this.isDarkTheme ? 'ant-drawer-dark' : '';
},
};
}
const themeSwitcher = createThemeSwitcher();
Vue.component('theme-switch', {
props: [],
template: `{{template "component/themeSwitchTemplate"}}`,
data: () => ({ themeSwitcher }),
});
</script>
{{end}}

View File

@@ -53,7 +53,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -69,7 +69,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -47,7 +47,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -79,7 +79,7 @@
</tr>
<tr v-else>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -45,7 +45,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -77,7 +77,7 @@
</tr>
<tr v-else>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -56,7 +56,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -88,7 +88,7 @@
</tr>
<tr v-else>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -53,7 +53,7 @@
</tr>
<tr>
<td>
<span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
@@ -85,7 +85,7 @@
</tr>
<tr v-else>
<td>
<span >{{ i18n "pages.inbounds.expireDate" }}</span>
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>

View File

@@ -5,7 +5,7 @@
sniffing
<a-tooltip>
<template slot="title">
<span >{{ i18n "pages.inbounds.noRecommendKeepDefault" }}</span>
<span>{{ i18n "pages.inbounds.noRecommendKeepDefault" }}</span>
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>

View File

@@ -175,7 +175,7 @@
<tr>
<td>uTLS</td>
<td>
<a-form-item >
<a-form-item>
<a-select v-model="inbound.stream.reality.settings.fingerprint"
style="width: 250px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>

View File

@@ -3,7 +3,7 @@
v-model="infoModal.visible" title='{{ i18n "pages.inbounds.details"}}'
:closable="true"
:mask-closable="true"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:footer="null"
width="600px"
>
@@ -81,7 +81,7 @@
<th>{{ i18n "pages.inbounds.expireDate" }}</th>
<tr>
<td>
<a-tag v-if="infoModal.clientStats" :color="green">
<a-tag v-if="infoModal.clientStats" color="green">
[[ sizeFormat(infoModal.clientStats['up']) ]] /
[[ sizeFormat(infoModal.clientStats['down']) ]]
([[ sizeFormat(infoModal.clientStats['up'] + infoModal.clientStats['down']) ]])

View File

@@ -1,7 +1,7 @@
{{define "inboundModal"}}
<a-modal id="inbound-modal" v-model="inModal.visible" :title="inModal.title" @ok="inModal.ok"
:confirm-loading="inModal.confirmLoading" :closable="true" :mask-closable="false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:ok-text="inModal.okText" cancel-text='{{ i18n "close" }}'>
{{template "form/inbound"}}
</a-modal>

View File

@@ -15,7 +15,7 @@
<body>
<a-layout id="app" v-cloak>
{{ template "commonSider" . }}
<a-layout id="content-layout" :style="siderDrawer.isDarkTheme ? bgDarkStyle : ''">
<a-layout id="content-layout" :style="themeSwitcher.bgStyle">
<a-layout-content>
<a-spin :spinning="spinning" :delay="500" tip="loading">
<transition name="list" appear>
@@ -24,7 +24,7 @@
</a-tag>
</transition>
<transition name="list" appear>
<a-card hoverable style="margin-bottom: 20px;" :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable style="margin-bottom: 20px;" :class="themeSwitcher.darkCardClass">
<a-row>
<a-col :xs="24" :sm="24" :lg="12">
{{ i18n "pages.inbounds.totalDownUp" }}:
@@ -64,7 +64,7 @@
</a-card>
</transition>
<transition name="list" appear>
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
<div slot="title">
<a-row>
<a-col :xs="24" :sm="24" :lg="12">
@@ -241,6 +241,7 @@
</a-layout>
</a-layout>
{{template "js" .}}
{{template "component/themeSwitcher" .}}
<script>
const columns = [{
title: '{{ i18n "pages.inbounds.operate" }}',
@@ -312,6 +313,7 @@
el: '#app',
data: {
siderDrawer,
themeSwitcher,
spinning: false,
inbounds: [],
dbInbounds: [],
@@ -477,7 +479,7 @@
openAddInbound() {
inModal.show({
title: '{{ i18n "pages.inbounds.addInbound"}}',
okText: '{{ i18n "pages.inbounds.addTo"}}',
okText: '{{ i18n "pages.inbounds.create"}}',
cancelText: '{{ i18n "close" }}',
confirm: async (inbound, dbInbound) => {
inModal.loading();
@@ -492,7 +494,7 @@
const inbound = dbInbound.toInbound();
inModal.show({
title: '{{ i18n "pages.inbounds.modifyInbound"}}',
okText: '{{ i18n "pages.inbounds.revise"}}',
okText: '{{ i18n "pages.inbounds.update"}}',
cancelText: '{{ i18n "close" }}',
inbound: inbound,
dbInbound: dbInbound,
@@ -508,7 +510,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.cloneInbound"}} ' + dbInbound.remark,
content: '{{ i18n "pages.inbounds.cloneInboundContent"}}',
okText: '{{ i18n "pages.inbounds.revise"}}',
okText: '{{ i18n "pages.inbounds.update"}}',
cancelText: '{{ i18n "cancel" }}',
onOk: () => {
const baseInbound = dbInbound.toInbound();
@@ -641,7 +643,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => {
@@ -656,7 +658,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.deleteInbound"}}',
content: '{{ i18n "pages.inbounds.deleteInboundContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "delete"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit('/xui/inbound/del/' + dbInboundId),
@@ -668,7 +670,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.deleteInbound"}}',
content: '{{ i18n "pages.inbounds.deleteInboundContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "delete"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit(`/xui/inbound/${dbInboundId}/delClient/${clientId}`),
@@ -733,7 +735,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit('/xui/inbound/' + dbInboundId + '/resetClientTraffic/'+ client.email),
@@ -743,7 +745,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.resetAllTrafficTitle"}}',
content: '{{ i18n "pages.inbounds.resetAllTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit('/xui/inbound/resetAllTraffics'),
@@ -753,7 +755,7 @@
this.$confirm({
title: dbInboundId>0 ? '{{ i18n "pages.inbounds.resetInboundClientTrafficTitle"}}' : '{{ i18n "pages.inbounds.resetAllClientTrafficTitle"}}',
content: dbInboundId>0 ? '{{ i18n "pages.inbounds.resetInboundClientTrafficContent"}}' : '{{ i18n "pages.inbounds.resetAllClientTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit('/xui/inbound/resetAllClientTraffics/' + dbInboundId),
@@ -763,7 +765,7 @@
this.$confirm({
title: '{{ i18n "pages.inbounds.delDepletedClientsTitle"}}',
content: '{{ i18n "pages.inbounds.delDepletedClientsContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: () => this.submit('/xui/inbound/delDepletedClients/' + dbInboundId),

View File

@@ -19,26 +19,26 @@
<body>
<a-layout id="app" v-cloak>
{{ template "commonSider" . }}
<a-layout id="content-layout" :style="siderDrawer.isDarkTheme ? bgDarkStyle : ''">
<a-layout id="content-layout" :style="themeSwitcher.bgStyle">
<a-layout-content>
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip"/>
<transition name="list" appear>
<a-row>
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
<a-row>
<a-col :sm="24" :md="12">
<a-row>
<a-col :span="12" style="text-align: center">
<a-progress type="dashboard" status="normal"
:stroke-color="status.cpu.color"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:percent="status.cpu.percent"></a-progress>
<div>CPU</div>
</a-col>
<a-col :span="12" style="text-align: center">
<a-progress type="dashboard" status="normal"
:stroke-color="status.mem.color"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:percent="status.mem.percent"></a-progress>
<div>
{{ i18n "pages.index.memory"}}: [[ sizeFormat(status.mem.current) ]] / [[ sizeFormat(status.mem.total) ]]
@@ -51,7 +51,7 @@
<a-col :span="12" style="text-align: center">
<a-progress type="dashboard" status="normal"
:stroke-color="status.swap.color"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:percent="status.swap.percent"></a-progress>
<div>
swap: [[ sizeFormat(status.swap.current) ]] / [[ sizeFormat(status.swap.total) ]]
@@ -60,7 +60,7 @@
<a-col :span="12" style="text-align: center">
<a-progress type="dashboard" status="normal"
:stroke-color="status.disk.color"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
:percent="status.disk.percent"></a-progress>
<div>
{{ i18n "pages.index.hard"}}: [[ sizeFormat(status.disk.current) ]] / [[ sizeFormat(status.disk.total) ]]
@@ -75,13 +75,13 @@
<transition name="list" appear>
<a-row>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
x-ui: <a-tag color="green">{{ .cur_ver }}</a-tag>
xray: <a-tag color="green" style="cursor: pointer;" @click="openSelectV2rayVersion">[[ status.xray.version ]]</a-tag>
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "pages.index.operationHours" }}:
<a-tag color="green">[[ formatSecond(status.uptime) ]]</a-tag>
<a-tooltip>
@@ -93,7 +93,7 @@
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "pages.index.xrayStatus" }}:
<a-tag :color="status.xray.color">[[ status.xray.state ]]</a-tag>
<a-tooltip v-if="status.xray.state === State.Error">
@@ -108,7 +108,7 @@
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "menu.link" }}:
<a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ i18n "pages.index.logs" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag>
@@ -116,12 +116,12 @@
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "pages.index.systemLoad" }}: [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
tcp / udp {{ i18n "pages.index.connectionCount" }}: [[ status.tcpCount ]] / [[ status.udpCount ]]
<a-tooltip>
<template slot="title">
@@ -132,7 +132,7 @@
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
<a-row>
<a-col :span="12">
<a-icon type="arrow-up"></a-icon>
@@ -158,7 +158,7 @@
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-card hoverable :class="themeSwitcher.darkCardClass">
<a-row>
<a-col :span="12">
<a-icon type="cloud-upload"></a-icon>
@@ -190,7 +190,7 @@
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}'
:closable="true" @ok="() => versionModal.visible = false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
footer="">
<h2>{{ i18n "pages.index.xraySwitchClick"}}</h2>
<h2>{{ i18n "pages.index.xraySwitchClickDesk"}}</h2>
@@ -204,7 +204,7 @@
<a-modal id="log-modal" v-model="logModal.visible" title="X-UI logs"
:closable="true" @ok="() => logModal.visible = false" @cancel="() => logModal.visible = false"
:class="siderDrawer.isDarkTheme ? darkClass : ''"
:class="themeSwitcher.darkCardClass"
width="800px"
footer="">
<a-form layout="inline">
@@ -234,7 +234,7 @@
</a-modal>
<a-modal id="backup-modal" v-model="backupModal.visible" :title="backupModal.title"
:closable="true" :class="siderDrawer.isDarkTheme ? darkClass : ''"
:closable="true" :class="themeSwitcher.darkCardClass"
@ok="() => backupModal.hide()" @cancel="() => backupModal.hide()">
<p style="color: inherit; font-size: 16px; padding: 4px 2px;">
<a-icon type="warning" style="color: inherit; font-size: 20px;"></a-icon>
@@ -252,6 +252,7 @@
</a-layout>
{{template "js" .}}
{{template "component/themeSwitcher" .}}
{{template "textModal"}}
<script>
@@ -386,6 +387,7 @@
el: '#app',
data: {
siderDrawer,
themeSwitcher,
status: new Status(),
versionModal,
logModal,
@@ -421,7 +423,7 @@
title: '{{ i18n "pages.index.xraySwitchVersionDialog"}}',
content: '{{ i18n "pages.index.xraySwitchVersionDialogDesc"}}' + ` ${version}?`,
okText: '{{ i18n "confirm"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
class: themeSwitcher.darkCardClass,
cancelText: '{{ i18n "cancel"}}',
onOk: async () => {
versionModal.hide();

View File

@@ -27,26 +27,15 @@
<body>
<a-layout id="app" v-cloak>
{{ template "commonSider" . }}
<a-layout id="content-layout" :style="siderDrawer.isDarkTheme ? bgDarkStyle : ''">
<a-layout id="content-layout" :style="themeSwitcher.bgStyle">
<a-layout-content>
<a-spin :spinning="spinning" :delay="500" tip="loading">
<a-space direction="vertical">
<a-space direction="horizontal">
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.setting.save" }}</a-button>
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.setting.restartPanel" }}</a-button>
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.settings.save" }}</a-button>
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button>
</a-space>
<a-tabs default-active-key="1" :class="siderDrawer.isDarkTheme ? darkClass : ''">
<a-tab-pane key="1" tab='{{ i18n "pages.setting.panelConfig"}}'>
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
<setting-list-item type="text" title='{{ i18n "pages.setting.panelListeningIP"}}' desc='{{ i18n "pages.setting.panelListeningIPDesc"}}' v-model="allSetting.webListen"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.setting.panelPort"}}' desc='{{ i18n "pages.setting.panelPortDesc"}}' v-model.number="allSetting.webPort"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.setting.sessionMaxAge" }}' desc='{{ i18n "pages.setting.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="0"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.setting.expireTimeDiff" }}' desc='{{ i18n "pages.setting.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.setting.trafficDiff" }}' desc='{{ i18n "pages.setting.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
<a-tabs default-active-key="1" :class="themeSwitcher.darkCardClass">
<a-list-item>
<a-row style="padding: 20px">
<a-col :lg="24" :xl="12">
@@ -59,7 +48,7 @@
ref="selectLang"
v-model="lang"
@change="setLang(lang)"
:dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"
:dropdown-class-name="themeSwitcher.darkCardClass"
style="width: 100%"
>
<a-select-option :value="l.value" :label="l.value" v-for="l in supportLangs">
@@ -74,19 +63,19 @@
</a-list-item>
</a-list>
</a-tab-pane>
<a-tab-pane key="2" tab='{{ i18n "pages.setting.userSetting"}}'>
<a-form :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65); padding: 20px;': 'background: white; padding: 20px;'">
<a-form-item label='{{ i18n "pages.setting.oldUsername"}}'>
<a-tab-pane key="2" tab='{{ i18n "pages.settings.userSetting"}}'>
<a-form :style="themeSwitcher.isDarkTheme ? 'color: hsla(0,0%,100%,.65); padding: 20px;': 'background: white; padding: 20px;'">
<a-form-item label='{{ i18n "pages.settings.oldUsername"}}'>
<a-input v-model="user.oldUsername" style="max-width: 300px"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.setting.currentPassword"}}'>
<a-form-item label='{{ i18n "pages.settings.currentPassword"}}'>
<a-input type="password" v-model="user.oldPassword"
style="max-width: 300px"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.setting.newUsername"}}'>
<a-form-item label='{{ i18n "pages.settings.newUsername"}}'>
<a-input v-model="user.newUsername" style="max-width: 300px"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.setting.newPassword"}}'>
<a-form-item label='{{ i18n "pages.settings.newPassword"}}'>
<a-input type="password" v-model="user.newPassword"
style="max-width: 300px"></a-input>
</a-form-item>
@@ -129,9 +118,7 @@
<setting-list-item type="number" title='{{ i18n "pages.setting.tgNotifyCpu" }}' desc='{{ i18n "pages.setting.tgNotifyCpuDesc" }}' v-model="allSetting.tgCpu" :min="0" :max="100"></setting-list-item>
</a-list>
</a-tab-pane>
<a-tab-pane key="5" tab='{{ i18n "pages.setting.otherSetting"}}'>
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
<setting-list-item type="text" title='{{ i18n "pages.setting.timeZonee"}}' desc='{{ i18n "pages.setting.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
<a-list item-layout="horizontal" :style="themeSwitcher.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
</a-list>
</a-tab-pane>
</a-tabs>
@@ -141,6 +128,7 @@
</a-layout>
</a-layout>
{{template "js" .}}
{{template "component/themeSwitcher" .}}
{{template "component/setting"}}
<script>
@@ -149,6 +137,7 @@
el: '#app',
data: {
siderDrawer,
themeSwitcher,
spinning: false,
oldAllSetting: new AllSetting(),
allSetting: new AllSetting(),
@@ -184,13 +173,14 @@
this.loading(false);
if (msg.success) {
this.user = {};
window.location.replace(basePath + "logout")
}
},
async restartPanel() {
await new Promise(resolve => {
this.$confirm({
title: '{{ i18n "pages.setting.restartPanel" }}',
content: '{{ i18n "pages.setting.restartPanelDesc" }}',
title: '{{ i18n "pages.settings.restartPanel" }}',
content: '{{ i18n "pages.settings.restartPanelDesc" }}',
okText: '{{ i18n "sure" }}',
cancelText: '{{ i18n "cancel" }}',
onOk: () => resolve(),
@@ -202,7 +192,7 @@
if (msg.success) {
this.loading(true);
await PromiseUtil.sleep(5000);
location.reload();
window.location.replace(this.allSetting.webBasePath + "xui/settings");
}
},
async resetXrayConfigToDefault() {