refactor: ♻️ 登录页面优化

This commit is contained in:
ray
2024-09-09 00:48:11 +08:00
parent 3341abef64
commit 248b86fe3c
8 changed files with 225 additions and 115 deletions

View File

@@ -0,0 +1 @@
<svg t="1725812178308" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4564" width="200" height="200"><path d="M512 1024C229.234 1024 0 794.766 0 512S229.234 0 512 0s512 229.234 512 512-229.234 512-512 512z m259.157-568.889l-290.759 0.014c-13.966 0-25.287 11.321-25.287 25.273l-0.028 63.218c0 13.966 11.306 25.287 25.273 25.287H657.38c13.966 0 25.287 11.307 25.287 25.273v12.644a75.847 75.847 0 0 1-75.847 75.847H366.606a25.287 25.287 0 0 1-25.287-25.273v-240.2a75.847 75.847 0 0 1 75.847-75.846l353.92-0.015c13.966 0 25.273-11.306 25.287-25.273l0.071-63.189c0-13.966-11.306-25.287-25.272-25.301l-353.992 0.014c-104.718-0.014-189.624 84.892-189.624 189.61v353.963c0 13.967 11.32 25.287 25.287 25.287h372.935c94.265 0 170.666-76.401 170.666-170.666v-145.38c0-13.952-11.32-25.273-25.287-25.273z" p-id="4565"></path></svg>

After

Width:  |  Height:  |  Size: 864 B

1
src/assets/icons/qq.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19.9139 14.529C19.7336 13.955 19.4877 13.2856 19.2385 12.643L18.3288 10.3969C18.3295 10.371 18.3408 9.92858 18.3408 9.70053C18.3408 5.8599 16.5082 2.00037 12.0009 2C7.49403 2.00037 5.66113 5.8599 5.66113 9.70053C5.66113 9.92858 5.67237 10.371 5.67312 10.3969L4.76379 12.643C4.51453 13.2856 4.26827 13.955 4.08798 14.529C3.2285 17.2657 3.507 18.3982 3.71915 18.4238C4.17419 18.4779 5.49021 16.3635 5.49021 16.3635C5.49021 17.5879 6.12741 19.1858 7.5064 20.3398C6.99064 20.4971 6.35868 20.7388 5.95237 21.0355C5.58729 21.3025 5.63302 21.5743 5.69861 21.6841C5.9876 22.1661 10.6542 21.9918 12.0017 21.8417C13.3488 21.9918 18.0158 22.1661 18.3044 21.6841C18.3704 21.5743 18.4157 21.3025 18.0507 21.0355C17.6443 20.7388 17.012 20.4971 16.4959 20.3395C17.8745 19.1858 18.5117 17.5879 18.5117 16.3635C18.5117 16.3635 19.8281 18.4779 20.2831 18.4238C20.4949 18.3982 20.7734 17.2657 19.9139 14.529Z"></path></svg>

After

Width:  |  Height:  |  Size: 995 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M18.5753 13.7114C19.0742 13.7114 19.4733 13.2873 19.4733 12.8134C19.4733 12.3145 19.0742 11.9155 18.5753 11.9155C18.0765 11.9155 17.6774 12.3145 17.6774 12.8134C17.6774 13.3123 18.0765 13.7114 18.5753 13.7114ZM14.1497 13.7114C14.6485 13.7114 15.0476 13.2873 15.0476 12.8134C15.0476 12.3145 14.6485 11.9155 14.1497 11.9155C13.6508 11.9155 13.2517 12.3145 13.2517 12.8134C13.2517 13.3123 13.6508 13.7114 14.1497 13.7114ZM20.717 18.7516C20.5942 18.8253 20.5205 18.9482 20.5451 19.1202C20.5451 19.1693 20.5451 19.2185 20.5696 19.2676C20.6679 19.6854 20.8643 20.349 20.8643 20.3736C20.8643 20.4473 20.8889 20.4964 20.8889 20.5456C20.8889 20.6685 20.7907 20.7668 20.6679 20.7668C20.6187 20.7668 20.5942 20.7422 20.5451 20.7176L19.0961 19.882C18.9978 19.8329 18.875 19.7837 18.7522 19.7837C18.6786 19.7837 18.6049 19.7837 18.5558 19.8083C17.8681 20.0049 17.1559 20.1032 16.3946 20.1032C12.7352 20.1032 9.78815 17.6456 9.78815 14.5983C9.78815 11.5509 12.7352 9.09329 16.3946 9.09329C20.0539 9.09329 23.001 11.5509 23.001 14.5983C23.001 16.2448 22.1168 17.7439 20.717 18.7516ZM16.6737 8.09757C16.581 8.09473 16.488 8.09329 16.3946 8.09329C12.2199 8.09329 8.78815 10.9536 8.78815 14.5983C8.78815 15.1519 8.86733 15.6874 9.01626 16.1975H8.92711C8.04096 16.1975 7.15481 16.0503 6.3425 15.8296C6.26866 15.805 6.19481 15.805 6.12097 15.805C5.97327 15.805 5.82558 15.8541 5.7025 15.9277L3.95482 16.9334C3.90559 16.958 3.85635 16.9825 3.80712 16.9825C3.65943 16.9825 3.53636 16.8599 3.53636 16.7127C3.53636 16.6391 3.56097 16.59 3.58559 16.5164C3.6102 16.4919 3.83174 15.6824 3.95482 15.1918C3.95482 15.1427 3.97943 15.0691 3.97943 15.0201C3.97943 14.8238 3.88097 14.6766 3.75789 14.5785C2.05944 13.3765 1.00098 11.5858 1.00098 9.59876C1.00098 5.94369 4.5702 3 8.95173 3C12.7157 3 15.8802 5.16856 16.6737 8.09757ZM11.5199 8.51604C12.0927 8.51604 12.5462 8.03871 12.5462 7.4898C12.5462 6.91701 12.0927 6.46356 11.5199 6.46356C10.9471 6.46356 10.4937 6.91701 10.4937 7.4898C10.4937 8.06258 10.9471 8.51604 11.5199 8.51604ZM6.26045 8.51604C6.83324 8.51604 7.28669 8.03871 7.28669 7.4898C7.28669 6.91701 6.83324 6.46356 6.26045 6.46356C5.68767 6.46356 5.23421 6.91701 5.23421 7.4898C5.23421 8.06258 5.68767 8.51604 6.26045 8.51604Z"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -11,6 +11,8 @@ export default {
login: "Login",
captchaCode: "Verify Code",
capsLock: "Caps Lock is On",
rememberMe: "Remember Me",
forgetPassword: "Forget Password",
message: {
username: {
required: "Please enter Username",
@@ -23,6 +25,7 @@ export default {
required: "Please enter Verify Code",
},
},
otherLoginMethods: "Other login methods",
},
// 导航栏国际化
navbar: {

View File

@@ -11,6 +11,8 @@ export default {
login: "登 录",
captchaCode: "验证码",
capsLock: "大写锁定已打开",
rememberMe: "记住我",
forgetPassword: "忘记密码",
message: {
username: {
required: "请输入用户名",
@@ -23,6 +25,7 @@ export default {
required: "请输入验证码",
},
},
otherLoginMethods: "其他登录方式",
},
// 导航栏国际化
navbar: {

View File

@@ -8,25 +8,47 @@
background: url("@/assets/images/login-background-light.jpg") no-repeat center
right;
.top-bar {
position: absolute;
top: 0;
left: 0;
.login-content {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
padding: 10px;
}
min-width: 400px;
max-width: 850px;
overflow: hidden;
background-color: #fff;
border-radius: 5px;
box-shadow: var(--el-box-shadow-light);
.login-card {
width: 400px;
background: transparent;
border: none;
border-radius: 4%;
@media (width <= 768px) {
flex-direction: column;
max-width: 100%;
height: 100vh;
border-radius: 0;
box-shadow: none;
}
@media (width <= 640px) {
width: 340px;
.login-image {
display: flex;
flex: 3;
align-items: center;
justify-content: center;
background: linear-gradient(60deg, #165dff, #6aa1ff);
@media (width <= 768px) {
display: none;
}
}
.login-box {
display: flex;
flex: 2;
flex-direction: column;
justify-content: center;
min-width: 400px;
padding: 30px;
@media (width <= 768px) {
width: 100%;
}
}
.input-wrapper {
@@ -43,13 +65,6 @@
}
}
.icp-info {
position: absolute;
bottom: 4px;
font-size: 12px;
text-align: center;
}
.el-form-item {
background: var(--el-input-bg-color);
border: 1px solid var(--el-border-color);
@@ -75,7 +90,14 @@
}
}
html.dark .login-container {
background: url("@/assets/images/login-background-dark.jpg") no-repeat center
right;
html.dark {
.login-container {
background: url("@/assets/images/login-background-dark.jpg") no-repeat
center right;
.login-content {
background: transparent;
box-shadow: var(--el-box-shadow);
}
}
}

View File

@@ -1,115 +1,181 @@
<template>
<div class="login-container">
<!-- 顶部工具栏 -->
<div class="top-bar">
<el-switch
v-model="isDark"
inline-prompt
active-icon="Moon"
inactive-icon="Sunny"
@change="toggleTheme"
/>
<lang-select class="ml-2 cursor-pointer" />
</div>
<!-- 登录表单 -->
<el-card class="login-card">
<div class="text-center relative">
<h2>{{ defaultSettings.title }}</h2>
<el-tag class="ml-2 absolute-rt">{{ defaultSettings.version }}</el-tag>
<div class="flex-x-between absolute-lt w-full p-2">
<div class="flex-center">
<el-image :src="logo" style="width: 34px; height: 30px" />
<span class="text-xl font-medium mx-1">
{{ defaultSettings.title }}
</span>
<el-tag size="small" type="success">
{{ defaultSettings.version }}
</el-tag>
</div>
<el-form
ref="loginFormRef"
:model="loginData"
:rules="loginRules"
class="login-form"
>
<!-- 用户名 -->
<el-form-item prop="username">
<div class="input-wrapper">
<i-ep-user class="mx-2" />
<el-input
ref="username"
v-model="loginData.username"
:placeholder="$t('login.username')"
name="username"
size="large"
class="h-[48px]"
/>
</div>
</el-form-item>
<div class="flex-center">
<el-switch
v-model="isDark"
inline-prompt
active-icon="Moon"
inactive-icon="Sunny"
@change="toggleTheme"
/>
<lang-select class="ml-2 cursor-pointer" />
</div>
</div>
<!-- 密码 -->
<el-tooltip
:visible="isCapslock"
:content="$t('login.capsLock')"
placement="right"
<!-- 登录表单 -->
<div class="login-content">
<div class="login-image">
<el-image :src="loginImage" style="width: 210px; height: 210px" />
</div>
<div class="login-box">
<el-form
ref="loginFormRef"
:model="loginData"
:rules="loginRules"
class="login-form"
>
<el-form-item prop="password">
<h2 class="text-xl font-medium text-center flex-center relative">
{{ $t("login.login") }}
<el-dropdown style="position: absolute; right: 0">
<div class="cursor-pointer">
<el-icon>
<arrow-down />
</el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
@click="setLoginCredentials('root', '123456')"
>
超级管理员root/123456
</el-dropdown-item>
<el-dropdown-item
@click="setLoginCredentials('admin', '123456')"
>
系统管理员admin/123456
</el-dropdown-item>
<el-dropdown-item
@click="setLoginCredentials('test', '123456')"
>
测试小游客test/123456
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</h2>
<!-- 用户名 -->
<el-form-item prop="username">
<div class="input-wrapper">
<i-ep-lock class="mx-2" />
<i-ep-user class="mx-2" />
<el-input
v-model="loginData.password"
:placeholder="$t('login.password')"
type="password"
name="password"
@keyup="checkCapslock"
@keyup.enter="handleLoginSubmit"
ref="username"
v-model="loginData.username"
:placeholder="$t('login.username')"
name="username"
size="large"
class="h-[48px] pr-2"
show-password
class="h-[48px]"
/>
</div>
</el-form-item>
</el-tooltip>
<!-- 验证 -->
<el-form-item prop="captchaCode">
<div class="input-wrapper">
<svg-icon icon-class="captcha" class="mx-2" />
<el-input
v-model="loginData.captchaCode"
auto-complete="off"
size="large"
class="flex-1"
:placeholder="$t('login.captchaCode')"
@keyup.enter="handleLoginSubmit"
/>
<!-- -->
<el-tooltip
:visible="isCapslock"
:content="$t('login.capsLock')"
placement="right"
>
<el-form-item prop="password">
<div class="input-wrapper">
<i-ep-lock class="mx-2" />
<el-input
v-model="loginData.password"
:placeholder="$t('login.password')"
type="password"
name="password"
@keyup="checkCapslock"
@keyup.enter="handleLoginSubmit"
size="large"
class="h-[48px] pr-2"
show-password
/>
</div>
</el-form-item>
</el-tooltip>
<el-image
@click="getCaptcha"
:src="captchaBase64"
class="captcha-image"
/>
<!-- 验证码 -->
<el-form-item prop="captchaCode">
<div class="input-wrapper">
<svg-icon icon-class="captcha" class="mx-2" />
<el-input
v-model="loginData.captchaCode"
auto-complete="off"
size="large"
class="flex-1"
:placeholder="$t('login.captchaCode')"
@keyup.enter="handleLoginSubmit"
/>
<el-image
@click="getCaptcha"
:src="captchaBase64"
class="captcha-image"
/>
</div>
</el-form-item>
<div class="flex-x-between w-full py-1">
<el-checkbox>
{{ $t("login.rememberMe") }}
</el-checkbox>
<el-link type="primary" href="/forget-password">
{{ $t("login.forgetPassword") }}
</el-link>
</div>
</el-form-item>
<!-- 登录按钮 -->
<el-button
:loading="loading"
type="primary"
size="large"
class="w-full"
@click.prevent="handleLoginSubmit"
>
{{ $t("login.login") }}
</el-button>
<!-- 登录按钮 -->
<el-button
:loading="loading"
type="primary"
size="large"
class="w-full"
@click.prevent="handleLoginSubmit"
>
{{ $t("login.login") }}
</el-button>
<!-- 账号密码提示 -->
<div class="mt-10 text-sm">
<span>{{ $t("login.username") }}: admin</span>
<span class="ml-4">{{ $t("login.password") }}: 123456</span>
</div>
</el-form>
</el-card>
<el-divider>
<span class="text-12px">{{ $t("login.otherLoginMethods") }}</span>
</el-divider>
<!-- 第三方登录 -->
<div class="flex-x-center text-lg color-gray-5">
<svg-icon icon-class="wechat" class="cursor-pointer" />
<svg-icon icon-class="qq" class="cursor-pointer ml-5" />
<svg-icon icon-class="github" class="cursor-pointer ml-5" />
<svg-icon icon-class="gitee" class="cursor-pointer ml-5" />
</div>
</el-form>
</div>
</div>
<!-- ICP备案 -->
<div class="icp-info" v-show="icpVisible">
<div class="absolute bottom-0 w-full text-center text-12px">
<p>
Copyright © 2021 - 2024 youlai.tech All Rights Reserved. 有来技术
版权所有
Copyright © 2021 - 2024 youlai.tech All Rights Reserved.
<a
href="http://beian.miit.gov.cn/"
target="_blank"
rel="noopener noreferrer"
class="hover:underline"
>
皖ICP备20006496号-2
</a>
</p>
<p>皖ICP备20006496号-3</p>
</div>
</div>
</template>
@@ -153,6 +219,12 @@ const captchaBase64 = ref();
// 登录表单ref
const loginFormRef = ref<FormInstance>();
const logo = ref(new URL(`../../assets/logo.png`, import.meta.url).href);
const loginImage = ref(
new URL(`../../assets/images/login-image.svg`, import.meta.url).href
);
const loginData = ref<LoginData>({
username: "admin",
password: "123456",
@@ -263,6 +335,12 @@ function checkCapslock(event: KeyboardEvent) {
}
}
/** 设置登录凭证 */
const setLoginCredentials = (username: string, password: string) => {
loginData.value.username = username;
loginData.value.password = password;
};
onMounted(() => {
getCaptcha();
});