3x-ui/web/html/component/aThemeSwitch.html
2026-02-18 21:37:22 +03:30

154 lines
5.4 KiB
HTML

{{define "component/themeSwitchTemplate"}}
<template>
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" selected-keys="">
<a-sub-menu>
<span slot="title">
<a-icon type="bulb" :theme="themeSwitcher.currentTheme === 'light' ? 'outlined' : 'filled'"></a-icon>
<span>{{ i18n "menu.theme" }}</span>
</span>
<a-menu-item
id="change-theme"
class="ant-menu-theme-switch theme-picker-item"
:style="{ height: 'auto', lineHeight: 'normal', paddingTop: '8px', paddingBottom: '8px' }"
@mousedown.stop="themeSwitcher.animationsOff()"
@click.stop>
<a-radio-group :value="themeSwitcher.selectedTheme" @change="themeSwitcher.selectTheme($event.target.value)" @click.stop>
<a-space direction="vertical" :size="8">
<a-radio value="light">Light</a-radio>
<a-radio value="dark">{{ i18n "menu.dark" }}</a-radio>
<a-radio value="ultra-dark">{{ i18n "menu.ultraDark" }}</a-radio>
<a-radio value="cyberpunk">Cyberpunk</a-radio>
</a-space>
</a-radio-group>
</a-menu-item>
</a-sub-menu>
</a-menu>
</template>
{{end}}
{{define "component/themeSwitchTemplateLogin"}}
<template>
<a-space @mousedown="themeSwitcher.animationsOff()" id="change-theme" direction="vertical" :size="10" :style="{ width: '100%' }">
<a-radio-group :value="themeSwitcher.selectedTheme" @change="themeSwitcher.selectTheme($event.target.value)">
<a-space direction="vertical" :size="8">
<a-radio value="light">Light</a-radio>
<a-radio value="dark">{{ i18n "menu.dark" }}</a-radio>
<a-radio value="ultra-dark">{{ i18n "menu.ultraDark" }}</a-radio>
<a-radio value="cyberpunk">Cyberpunk</a-radio>
</a-space>
</a-radio-group>
</a-space>
</template>
{{end}}
{{define "component/aThemeSwitch"}}
<style>
.theme-picker-item.ant-menu-item-selected {
background: transparent !important;
border-color: transparent !important;
}
</style>
<script>
function createThemeSwitcher() {
const isDarkTheme = localStorage.getItem('dark-mode') === 'true';
const isUltra = localStorage.getItem('isUltraDarkThemeEnabled') === 'true';
const isCyberpunk = localStorage.getItem('cyberpunk-mode') === 'true';
const selectedTheme = isCyberpunk
? 'cyberpunk'
: isUltra
? 'ultra-dark'
: isDarkTheme
? 'dark'
: 'light';
function applyTheme(theme) {
const body = document.querySelector('body');
const root = document.documentElement;
const dark = theme !== 'light';
const ultra = theme === 'ultra-dark';
const cyberpunk = theme === 'cyberpunk';
body.setAttribute('class', dark ? 'dark' : 'light');
body.classList.toggle('cyberpunk', cyberpunk);
if (ultra) {
root.setAttribute('data-theme', 'ultra-dark');
} else {
root.removeAttribute('data-theme');
}
localStorage.setItem('dark-mode', dark.toString());
localStorage.setItem('isUltraDarkThemeEnabled', ultra.toString());
localStorage.setItem('cyberpunk-mode', cyberpunk.toString());
}
applyTheme(selectedTheme);
return {
selectedTheme,
isDarkTheme: selectedTheme !== 'light',
isUltra: selectedTheme === 'ultra-dark',
isCyberpunk: selectedTheme === 'cyberpunk',
syncFlags() {
this.isDarkTheme = this.selectedTheme !== 'light';
this.isUltra = this.selectedTheme === 'ultra-dark';
this.isCyberpunk = this.selectedTheme === 'cyberpunk';
},
animationsOff() {
document.documentElement.setAttribute('data-theme-animations', 'off');
const themeAnimations = document.querySelector('#change-theme');
themeAnimations.addEventListener('mouseleave', () => {
document.documentElement.removeAttribute('data-theme-animations');
});
themeAnimations.addEventListener('touchend', () => {
document.documentElement.removeAttribute('data-theme-animations');
});
},
get currentTheme() {
return this.selectedTheme === 'light' ? 'light' : 'dark';
},
selectTheme(theme) {
this.selectedTheme = theme;
this.syncFlags();
applyTheme(theme);
document.getElementById('message').className = this.currentTheme;
},
toggleTheme() {
this.selectTheme(this.currentTheme === 'light' ? 'dark' : 'light');
},
toggleUltra() {
this.selectTheme(this.selectedTheme === 'ultra-dark' ? 'dark' : 'ultra-dark');
},
toggleCyberpunk() {
this.selectTheme(this.selectedTheme === 'cyberpunk' ? 'dark' : 'cyberpunk');
}
};
}
const themeSwitcher = createThemeSwitcher();
Vue.component('a-theme-switch', {
template: `{{template "component/themeSwitchTemplate"}}`,
data: () => ({
themeSwitcher
}),
mounted() {
this.$message.config({
getContainer: () => document.getElementById('message')
});
document.getElementById('message').className = themeSwitcher.currentTheme;
}
});
Vue.component('a-theme-switch-login', {
template: `{{template "component/themeSwitchTemplateLogin"}}`,
data: () => ({
themeSwitcher
}),
mounted() {
this.$message.config({
getContainer: () => document.getElementById('message')
});
document.getElementById('message').className = themeSwitcher.currentTheme;
}
});
</script>
{{end}}