diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/html/login.html | 381 | ||||
| -rw-r--r-- | web/html/xui/component/aThemeSwitch.html | 33 |
2 files changed, 239 insertions, 175 deletions
diff --git a/web/html/login.html b/web/html/login.html index b27333a5..9a42aefe 100644 --- a/web/html/login.html +++ b/web/html/login.html @@ -6,27 +6,33 @@ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } + h1 { text-align: center; -/* margin: 20px 0 50px 0;*/ + /* margin: 20px 0 50px 0;*/ height: 110px; } + .ant-btn, .ant-input { height: 50px; 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; } + .ant-input-affix-wrapper .ant-input:not(:first-child) { padding-left: 50px; } + .centered { display: flex; text-align: center; @@ -34,68 +40,76 @@ justify-content: center; width: 100%; } + .title { font-size: 32px; } + .title b { font-weight: bold !important; } + #app { overflow: hidden; } + #login { animation: charge 0.5s both; background-color: #fff; border-radius: 2rem; padding: 3rem; transition: all 0.3s; - user-select:none; - -webkit-user-select:none; + user-select: none; + -webkit-user-select: none; -moz-user-select: none; } + #login:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09); } + @keyframes charge { from { transform: translateY(5rem); opacity: 0; } + to { transform: translateY(0); opacity: 1; } } + .under { background-color: #c7ebe2; z-index: 0; } + .dark .under { background-color: var(--dark-color-login-wave); } + .dark #login { background-color: var(--dark-color-surface-100); } + .dark h1 { color: rgba(255, 255, 255); } - .ant-form-item { - margin-bottom: 16px; - } + .ant-btn-primary-login { width: 100%; } + .ant-btn-primary-login:focus, .ant-btn-primary-login:hover { color: #fff; background-color: #006655; border-color: #006655; - background-image: linear-gradient( - 270deg, - rgba(123, 199, 77, 0) 30%, - #009980, - rgba(123, 199, 77, 0) 100% - ); + background-image: linear-gradient(270deg, + rgba(123, 199, 77, 0) 30%, + #009980, + rgba(123, 199, 77, 0) 100%); background-repeat: no-repeat; animation: ma-bg-move ease-in-out 5s infinite; background-position-x: -500px; @@ -103,29 +117,35 @@ animation-delay: -0.5s; box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); } + .ant-btn-primary-login.active, .ant-btn-primary-login:active { color: #fff; background-color: #006655; border-color: #006655; } + @keyframes ma-bg-move { 0% { background-position: -500px 0; } + 50% { background-position: 1000px 0; } + 100% { background-position: 1000px 0; } } + .wave-btn-bg { position: relative; border-radius: 25px; width: 100%; - transition: all 0.3s cubic-bezier(.645,.045,.355,1); + transition: all 0.3s cubic-bezier(.645, .045, .355, 1); } + .dark .wave-btn-bg { color: #fff; position: relative; @@ -137,15 +157,21 @@ width: 100%; z-index: 1; } - .dark .wave-btn-bg:hover {animation: wave-btn-tara 4s ease infinite;} + + .dark .wave-btn-bg:hover { + animation: wave-btn-tara 4s ease infinite; + } + .dark .wave-btn-bg-cl { background-image: linear-gradient(rgba(13, 14, 33, 0), rgba(13, 14, 33, 0)), radial-gradient(circle at left top, #006655, #009980, #006655) !important; border-radius: 3em; } + .dark .wave-btn-bg-cl:hover { width: 95%; } + .dark .wave-btn-bg-cl:before { position: absolute; content: ""; @@ -160,24 +186,25 @@ opacity: 0; transition: 0.5s; } + .dark .wave-btn-bg-cl:hover::before { opacity: 1; filter: blur(20px); animation: wave-btn-tara 8s linear infinite; } + @keyframes wave-btn-tara { to { background-position: 300%; } } + .dark .ant-btn-primary-login { font-size: 14px; color: #fff; text-align: center; - background-image: linear-gradient( - rgba(13, 14, 33, 0.45), - rgba(13, 14, 33, 0.35) - ); + background-image: linear-gradient(rgba(13, 14, 33, 0.45), + rgba(13, 14, 33, 0.35)); border-radius: 2rem; border: none; outline: none; @@ -193,6 +220,7 @@ background-position-x: 0; box-shadow: none; } + .waves-header { position: fixed; width: 100%; @@ -201,68 +229,83 @@ color: white; z-index: -1; } + .dark .waves-header { background-color: var(--dark-color-login-background); } + .waves-inner-header { height: 50vh; width: 100%; margin: 0; padding: 0; } + .waves { position: relative; width: 100%; height: 15vh; - margin-bottom: -8px; /*Fix for safari gap*/ + margin-bottom: -8px; + /*Fix for safari gap*/ min-height: 100px; max-height: 150px; } - .parallax > use { + + .parallax>use { animation: move-forever 25s cubic-bezier(0.55, 0.5, 0.45, 0.5) infinite; } - .dark .parallax > use { + + .dark .parallax>use { fill: var(--dark-color-login-wave); } - .parallax > use:nth-child(1) { + + .parallax>use:nth-child(1) { animation-delay: -2s; animation-duration: 4s; opacity: 0.2; } - .parallax > use:nth-child(2) { + + .parallax>use:nth-child(2) { animation-delay: -3s; animation-duration: 7s; opacity: 0.4; } - .parallax > use:nth-child(3) { + + .parallax>use:nth-child(3) { animation-delay: -4s; animation-duration: 10s; opacity: 0.6; } - .parallax > use:nth-child(4) { - animation-delay: -5s; - animation-duration: 13s; + + .parallax>use:nth-child(4) { + animation-delay: -5s; + animation-duration: 13s; } + @keyframes move-forever { 0% { transform: translate3d(-90px, 0, 0); } + 100% { transform: translate3d(85px, 0, 0); } } + @media (max-width: 768px) { .waves { height: 40px; min-height: 40px; } } + .words-wrapper { width: 100%; display: inline-block; position: relative; text-align: center; } + .words-wrapper b { width: 100%; display: inline-block; @@ -270,33 +313,40 @@ left: 0; top: 0; } + .words-wrapper b.is-visible { position: relative; } + .headline.zoom .words-wrapper { -webkit-perspective: 300px; -moz-perspective: 300px; perspective: 300px; } + .headline { display: flex; justify-content: center; align-items: center; } + .headline.zoom b { opacity: 0; } + .headline.zoom b.is-visible { opacity: 1; -webkit-animation: zoom-in 0.8s; -moz-animation: zoom-in 0.8s; animation: cubic-bezier(0.215, 0.610, 0.355, 1.000) zoom-in 0.8s; } + .headline.zoom b.is-hidden { -webkit-animation: zoom-out 0.8s; -moz-animation: zoom-out 0.8s; animation: cubic-bezier(0.215, 0.610, 0.355, 1.000) zoom-out 0.4s; } + @-webkit-keyframes zoom-in { 0% { opacity: 0; @@ -308,16 +358,19 @@ -webkit-transform: translateZ(0); } } + @-moz-keyframes zoom-in { 0% { opacity: 0; -moz-transform: translateZ(100px); } + 100% { opacity: 1; -moz-transform: translateZ(0); } } + @keyframes zoom-in { 0% { opacity: 0; @@ -327,6 +380,7 @@ -o-transform: translateZ(100px); transform: translateZ(100px); } + 100% { opacity: 1; -webkit-transform: translateZ(0); @@ -336,26 +390,31 @@ transform: translateZ(0); } } + @-webkit-keyframes zoom-out { 0% { opacity: 1; -webkit-transform: translateZ(0); } + 100% { opacity: 0; -webkit-transform: translateZ(-100px); } } + @-moz-keyframes zoom-out { 0% { opacity: 1; -moz-transform: translateZ(0); } + 100% { opacity: 0; -moz-transform: translateZ(-100px); } } + @keyframes zoom-out { 0% { opacity: 1; @@ -365,6 +424,7 @@ -o-transform: translateZ(0); transform: translateZ(0); } + 100% { opacity: 0; -webkit-transform: translateZ(-100px); @@ -374,13 +434,20 @@ transform: translateZ(-100px); } } - .ant-menu-item .anticon { - margin-right: 4px; + + .setting-section { + position: absolute; + top: 0; + right: 0; + padding: 24px; } - .ant-menu-inline .ant-menu-item { - padding: 0 16px !important; + + .setting-section > .ant-btn { + width: 36px; + height: 36px; } </style> + <body> <a-layout id="app" v-cloak :class="themeSwitcher.currentTheme"> <transition name="list" appear> @@ -388,7 +455,7 @@ <div class="waves-header"> <div class="waves-inner-header"></div> <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> <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> @@ -400,70 +467,67 @@ </g> </svg> </div> + <div class="setting-section"> + <a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}' placement="bottomRight" trigger="click"> + <template slot="content"> + <a-space direction="vertical" :size="10"> + <a-theme-switch-login></a-theme-switch-login> + <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-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 v-text="l.name"></span> + </a-select-option> + </a-select> + </a-space> + </template> + <a-button shape="circle" icon="setting"></a-button> + </a-popover> + </div> <a-row type="flex" justify="center" align="middle" style="height: 100%; overflow: auto; overflow-x: hidden;"> <a-col :xs="22" :sm="20" :md="14" :lg="10" :xl="8" :xxl="6" id="login" style="margin: 3rem 0;"> <a-row type="flex" justify="center"> <a-col style="width: 100%;"> - <h1 class="title headline zoom"> + <h2 class="title headline zoom"> <span class="words-wrapper"> <b class="is-visible">{{ i18n "pages.login.hello" }}</b> <b>{{ i18n "pages.login.title" }}</b> </span> - </h1> + </h2> </a-col> </a-row> <a-row type="flex" justify="center"> <a-col span="24"> <a-form> - <a-form-item> - <a-input autocomplete="username" name="username" v-model.trim="user.username" placeholder='{{ i18n "username" }}' - @keydown.enter.native="login" autofocus> - <a-icon slot="prefix" type="user" style="font-size: 16px;"></a-icon> - </a-input> - </a-form-item> - <a-form-item> - <a-password-input autocomplete="password" name="password" icon="lock" v-model.trim="user.password" - placeholder='{{ i18n "password" }}' - @keydown.enter.native="login"> - </a-password-input> - </a-form-item> - <a-form-item v-if="secretEnable"> - <a-password-input autocomplete="secret" name="secret" icon="key" v-model.trim="user.loginSecret" - placeholder='{{ i18n "secretToken" }}' - @keydown.enter.native="login"> - </a-password-input> - </a-form-item> - <a-form-item> - <a-row justify="center" class="centered"> - <div style="height: 50px;" class="wave-btn-bg wave-btn-bg-cl" - :style="loading ? { width: '52px' } : { display: 'inline-block' }"> - <a-button class="ant-btn-primary-login" type="primary" - :loading="loading" @click="login" - :icon="loading ? 'poweroff' : undefined"> - [[ loading ? '' : '{{ i18n "login" }}' ]] - </a-button> - </div> - </a-row> - </a-form-item> - <a-form-item> - <a-row justify="center" class="centered"> - <a-col :span="24"> - <a-select ref="selectLang" v-model="lang" - @change="LanguageManager.setLanguage(lang)" style="width: 200px;" - :dropdown-class-name="themeSwitcher.currentTheme"> - <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 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"> - <a-theme-switch-login></a-theme-switch-login> - </a-row> - </a-form-item> + <a-space direction="vertical" size="middle"> + <a-form-item> + <a-input autocomplete="username" name="username" v-model.trim="user.username" + placeholder='{{ i18n "username" }}' @keydown.enter.native="login" autofocus> + <a-icon slot="prefix" type="user" style="font-size: 16px;"></a-icon> + </a-input> + </a-form-item> + <a-form-item> + <a-password-input autocomplete="password" name="password" icon="lock" v-model.trim="user.password" + placeholder='{{ i18n "password" }}' @keydown.enter.native="login"> + </a-password-input> + </a-form-item> + <a-form-item v-if="secretEnable"> + <a-password-input autocomplete="secret" name="secret" icon="key" v-model.trim="user.loginSecret" + placeholder='{{ i18n "secretToken" }}' @keydown.enter.native="login"> + </a-password-input> + </a-form-item> + <a-form-item> + <a-row justify="center" class="centered"> + <div :style="{ height: '50px', marginTop: '16px' }" class="wave-btn-bg wave-btn-bg-cl" + :style="loading ? { width: '52px' } : { display: 'inline-block' }"> + <a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login" + :icon="loading ? 'poweroff' : undefined"> + [[ loading ? '' : '{{ i18n "login" }}' ]] + </a-button> + </div> + </a-row> + </a-form-item> + </a-space> </a-form> </a-col> </a-row> @@ -472,86 +536,85 @@ </a-layout-content> </transition> </a-layout> -{{template "js" .}} -{{template "component/aThemeSwitch" .}} -{{template "component/aPasswordInput" .}} -<script> - class User { - constructor() { - this.username = ""; - this.password = ""; - } - } - const app = new Vue({ - delimiters: ['[[', ']]'], - el: '#app', - data: { - themeSwitcher, - loading: false, - user: new User(), - secretEnable: false, - lang: "" - }, - async created() { - this.lang = LanguageManager.getLanguage(); - this.secretEnable = await this.getSecretStatus(); - }, - methods: { - async login() { - this.loading = true; - const msg = await HttpUtil.post('/login', this.user); - this.loading = false; - if (msg.success) { - location.href = basePath + 'panel/'; - } + {{template "js" .}} + {{template "component/aThemeSwitch" .}} + {{template "component/aPasswordInput" .}} + <script> + const app = new Vue({ + delimiters: ['[[', ']]'], + el: '#app', + data: { + themeSwitcher, + loading: false, + user: { + username: "", + password: "", + loginSecret: "" + }, + secretEnable: false, + lang: "" }, - async getSecretStatus() { - this.loading = true; - const msg = await HttpUtil.post('/getSecretStatus'); - this.loading = false; - if (msg.success) { - this.secretEnable = msg.obj; - return msg.obj; - } + async mounted() { + this.lang = LanguageManager.getLanguage(); + this.secretEnable = await this.getSecretStatus(); }, - }, - }); - document.addEventListener("DOMContentLoaded", function() { - var animationDelay = 2000; - initHeadline(); - - function initHeadline() { - animateHeadline(document.querySelectorAll('.headline')); - } + methods: { + async login() { + this.loading = true; + const msg = await HttpUtil.post('/login', this.user); + this.loading = false; + if (msg.success) { + location.href = basePath + 'panel/'; + } + }, + async getSecretStatus() { + this.loading = true; + const msg = await HttpUtil.post('/getSecretStatus'); + this.loading = false; + if (msg.success) { + this.secretEnable = msg.obj; + return msg.obj; + } + }, + }, + }); - function animateHeadline(headlines) { - var duration = animationDelay; - headlines.forEach(function(headline) { - setTimeout(function() { - hideWord(headline.querySelector('.is-visible')); - }, duration); - }); - } + document.addEventListener("DOMContentLoaded", function () { + var animationDelay = 2000; + initHeadline(); - function hideWord(word) { - var nextWord = takeNext(word); - switchWord(word, nextWord); - setTimeout(function() { - hideWord(nextWord); - }, animationDelay); - } + function initHeadline() { + animateHeadline(document.querySelectorAll('.headline')); + } - function takeNext(word) { - return (word.nextElementSibling) ? word.nextElementSibling : word.parentElement.firstElementChild; - } + function animateHeadline(headlines) { + var duration = animationDelay; + headlines.forEach(function (headline) { + setTimeout(function () { + hideWord(headline.querySelector('.is-visible')); + }, duration); + }); + } - function switchWord(oldWord, newWord) { - oldWord.classList.remove('is-visible'); - oldWord.classList.add('is-hidden'); - newWord.classList.remove('is-hidden'); - newWord.classList.add('is-visible'); - } - }); -</script> + function hideWord(word) { + var nextWord = takeNext(word); + switchWord(word, nextWord); + setTimeout(function () { + hideWord(nextWord); + }, animationDelay); + } + + function takeNext(word) { + return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild; + } + + function switchWord(oldWord, newWord) { + oldWord.classList.remove('is-visible'); + oldWord.classList.add('is-hidden'); + newWord.classList.remove('is-hidden'); + newWord.classList.add('is-visible'); + } + }); + </script> </body> -</html> +</html>
\ No newline at end of file diff --git a/web/html/xui/component/aThemeSwitch.html b/web/html/xui/component/aThemeSwitch.html index 9a213ca6..2f76cd1b 100644 --- a/web/html/xui/component/aThemeSwitch.html +++ b/web/html/xui/component/aThemeSwitch.html @@ -6,13 +6,16 @@ <a-icon type="bulb" :theme="themeSwitcher.isDarkTheme ? 'filled' : 'outlined'"></a-icon> <span>{{ i18n "menu.theme" }}</span> </span> - <a-menu-item id="change-theme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOff()"> + <a-menu-item id="change-theme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOff()"> <span>{{ i18n "menu.dark" }}</span> - <a-switch style="margin-left: 2px;" size="small" :default-checked="themeSwitcher.isDarkTheme" @change="themeSwitcher.toggleTheme()"></a-switch> + <a-switch style="margin-left: 2px;" size="small" :default-checked="themeSwitcher.isDarkTheme" + @change="themeSwitcher.toggleTheme()"></a-switch> </a-menu-item> - <a-menu-item id="change-theme-ultra" v-if="themeSwitcher.isDarkTheme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOffUltra()"> + <a-menu-item id="change-theme-ultra" v-if="themeSwitcher.isDarkTheme" class="ant-menu-theme-switch" + @mousedown="themeSwitcher.animationsOffUltra()"> <span>{{ i18n "menu.ultraDark" }}</span> - <a-checkbox style="margin-left: 2px;" :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()"></a-checkbox> + <a-checkbox style="margin-left: 2px;" :checked="themeSwitcher.isUltra" + @click="themeSwitcher.toggleUltra()"></a-checkbox> </a-menu-item> </a-sub-menu> </a-menu> @@ -21,18 +24,16 @@ {{define "component/themeSwitchTemplateLogin"}} <template> - <a-menu @mousedown="themeSwitcher.animationsOff()" id="change-theme" :theme="themeSwitcher.currentTheme" mode="inline" - selected-keys=""> - <a-menu-item mode="inline" class="ant-menu-theme-switch"> - <a-icon type="bulb" :theme="themeSwitcher.isDarkTheme ? 'filled' : 'outlined'"></a-icon> - <a-switch size="small" :default-checked="themeSwitcher.isDarkTheme" - @change="themeSwitcher.toggleTheme()"></a-switch> - <template v-if="themeSwitcher.isDarkTheme"> - <a-checkbox style="margin-left: 1rem; vertical-align: middle;" :checked="themeSwitcher.isUltra" - @click="themeSwitcher.toggleUltra()">Ultra</a-checkbox> - </template> - </a-menu-item> - </a-menu> + <a-space direction="vertical" :size="10" :style="{ width: '100%' }"> + <a-space direction="horizontal" size="small"> + <a-switch size="small" :default-checked="themeSwitcher.isDarkTheme" @change="themeSwitcher.toggleTheme()"></a-switch> + <span>{{ i18n "menu.dark" }}</span> + </a-space> + <a-space v-if="themeSwitcher.isDarkTheme" direction="horizontal" size="small"> + <a-checkbox :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()"></a-checkbox> + <span>{{ i18n "menu.ultraDark" }}</span> + </a-space> + </a-space> </template> {{end}} |
