refactor!: 重构登录页面

This commit is contained in:
Hooray Hu 2024-08-06 02:18:25 +08:00
parent 6f59ddf6b8
commit cb230f77bd
6 changed files with 515 additions and 405 deletions

View File

@ -0,0 +1,172 @@
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import useUserStore from '@/store/modules/user'
defineOptions({
name: 'LoginForm',
})
const props = defineProps<{
account?: string
}>()
const emits = defineEmits<{
onLogin: [account: string]
onRegister: [account: string]
onResetPassword: [account: string]
}>()
const userStore = useUserStore()
const title = import.meta.env.VITE_APP_TITLE
const loading = ref(false)
// default qrcode
const type = ref('default')
const formRef = ref<FormInstance>()
const form = ref({
account: props.account ?? localStorage.login_account ?? '',
password: '',
remember: !!localStorage.login_account,
})
const rules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
password: [
{ required: true, trigger: 'blur', message: '请输入密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
})
function handleLogin() {
formRef.value?.validate((valid) => {
if (valid) {
loading.value = true
userStore.login(form.value).then(() => {
if (form.value.remember) {
localStorage.setItem('login_account', form.value.account)
}
else {
localStorage.removeItem('login_account')
}
emits('onLogin', form.value.account)
}).finally(() => {
loading.value = false
})
}
})
}
function testAccount(account: string) {
form.value.account = account
form.value.password = '123456'
handleLogin()
}
</script>
<template>
<ElForm ref="formRef" :model="form" :rules="rules" class="min-h-500px w-full flex-col-stretch-center p-12">
<div class="mb-6">
<HTabList
v-model="type" :options="[
{ label: '账号密码登录', value: 'default' },
{ label: '扫码登录', value: 'qrcode' },
]"
/>
</div>
<template v-if="type === 'default'">
<h3 class="mb-8 text-xl color-[var(--el-text-color-primary)] font-bold">
欢迎使用 {{ title }} ! 👋🏻
</h3>
<div>
<ElFormItem prop="account">
<ElInput v-model="form.account" placeholder="用户名" type="text" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="password">
<ElInput v-model="form.password" type="password" placeholder="密码" tabindex="2" show-password @keyup.enter="handleLogin">
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<div class="mb-4 flex-center-between">
<ElCheckbox v-model="form.remember">
记住我
</ElCheckbox>
<ElLink type="primary" :underline="false" @click="emits('onResetPassword', form.account)">
忘记密码了?
</ElLink>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%;" @click.prevent="handleLogin">
登录
</ElButton>
<div class="mt-4 flex-center gap-2 text-sm color-[var(--el-text-color-secondary)]">
还没有帐号?
<ElLink type="primary" :underline="false" @click="emits('onRegister', form.account)">
创建新帐号
</ElLink>
</div>
</template>
<template v-else-if="type === 'qrcode'">
<div class="flex-col-center">
<el-image src="https://s2.loli.net/2024/04/26/GsahtuIZ9XOg5jr.png" class="h-[250px] w-[250px]" />
<div class="mt-2 op-50">
请使用微信扫码登录
</div>
</div>
</template>
<div class="mt-4 text-center -mb-4">
<ElDivider>演示账号一键登录</ElDivider>
<ElButton type="primary" size="small" plain @click="testAccount('admin')">
admin
</ElButton>
<ElButton size="small" plain @click="testAccount('test')">
test
</ElButton>
</div>
</ElForm>
</template>
<style lang="scss" scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}
.el-form-item {
margin-bottom: 24px;
:deep(.el-input) {
width: 100%;
height: 48px;
line-height: inherit;
input {
height: 48px;
}
.el-input__prefix,
.el-input__suffix {
display: flex;
align-items: center;
}
.el-input__prefix {
left: 10px;
}
.el-input__suffix {
right: 10px;
}
}
}
:deep(.el-divider__text) {
white-space: nowrap;
background-color: var(--g-container-bg);
}
</style>

View File

@ -0,0 +1,148 @@
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'RegisterForm',
})
const props = defineProps<{
account?: string
}>()
const emits = defineEmits<{
onLogin: [account: string]
onRegister: [account: string]
}>()
const loading = ref(false)
const formRef = ref<FormInstance>()
const form = ref({
account: props.account ?? '',
captcha: '',
password: '',
checkPassword: '',
})
const rules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
captcha: [
{ required: true, trigger: 'blur', message: () => '请输入验证码' },
],
password: [
{ required: true, trigger: 'blur', message: '请输入密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
checkPassword: [
{ required: true, trigger: 'blur', message: '请再次输入密码' },
{
validator: (rule, value, callback) => {
if (value !== form.value.password) {
callback(new Error('两次输入的密码不一致'))
}
else {
callback()
}
},
},
],
})
function handleRegister() {
ElMessage({
message: '注册模块仅提供界面演示,无实际功能,需开发者自行扩展',
type: 'warning',
})
formRef.value?.validate((valid) => {
if (valid) {
//
emits('onRegister', form.value.account)
}
})
}
</script>
<template>
<ElForm ref="formRef" :model="form" :rules="rules" class="min-h-500px w-full flex-col-stretch-center p-12">
<h3 class="mb-8 text-xl color-[var(--el-text-color-primary)] font-bold">
探索从这里开始! 🚀
</h3>
<div>
<ElFormItem prop="account">
<ElInput v-model="form.account" placeholder="用户名" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="captcha">
<ElInput v-model="form.captcha" placeholder="验证码" tabindex="2">
<template #prefix>
<SvgIcon name="i-ic:baseline-verified-user" />
</template>
<template #append>
<ElButton>发送验证码</ElButton>
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="password">
<ElInput v-model="form.password" type="password" placeholder="密码" tabindex="3" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="checkPassword">
<ElInput v-model="form.checkPassword" type="password" placeholder="确认密码" tabindex="4" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%; margin-top: 20px;" @click.prevent="handleRegister">
注册
</ElButton>
<div class="mt-4 flex-center gap-2 text-sm color-[var(--el-text-color-secondary)]">
已经有帐号?
<ElLink type="primary" :underline="false" @click="emits('onLogin', form.account)">
去登录
</ElLink>
</div>
</ElForm>
</template>
<style lang="scss" scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}
.el-form-item {
margin-bottom: 24px;
:deep(.el-input) {
width: 100%;
height: 48px;
line-height: inherit;
input {
height: 48px;
}
.el-input__prefix,
.el-input__suffix {
display: flex;
align-items: center;
}
.el-input__prefix {
left: 10px;
}
.el-input__suffix {
right: 10px;
}
}
}
</style>

View File

@ -0,0 +1,126 @@
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
defineOptions({
name: 'ResetPasswordForm',
})
const props = defineProps<{
account?: string
}>()
const emits = defineEmits<{
onLogin: [account: string]
onResetPassword: [account: string]
}>()
const loading = ref(false)
const formRef = ref<FormInstance>()
const form = ref({
account: props.account ?? localStorage.login_account ?? '',
captcha: '',
newPassword: '',
})
const rules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
captcha: [
{ required: true, trigger: 'blur', message: '请输入验证码' },
],
newPassword: [
{ required: true, trigger: 'blur', message: '请输入新密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
})
function handleReset() {
ElMessage({
message: '重置密码仅提供界面演示,无实际功能,需开发者自行扩展',
type: 'info',
})
formRef.value?.validate((valid) => {
if (valid) {
//
emits('onResetPassword', form.value.account)
}
})
}
</script>
<template>
<ElForm ref="formRef" :model="form" :rules="rules" class="min-h-500px w-full flex-col-stretch-center p-12">
<h3 class="mb-8 text-xl color-[var(--el-text-color-primary)] font-bold">
忘记密码了? 🔒
</h3>
<div>
<ElFormItem prop="account">
<ElInput v-model="form.account" placeholder="用户名" type="text" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="captcha">
<ElInput v-model="form.captcha" placeholder="验证码" type="text" tabindex="2">
<template #prefix>
<SvgIcon name="i-ic:baseline-verified-user" />
</template>
<template #append>
<ElButton>发送验证码</ElButton>
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="newPassword">
<ElInput v-model="form.newPassword" type="password" placeholder="新密码" tabindex="3" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%; margin-top: 20px;" @click.prevent="handleReset">
确认
</ElButton>
<div class="mt-4 flex-center gap-2 text-sm color-[var(--el-text-color-secondary)]">
<ElLink type="primary" :underline="false" @click="emits('onLogin', form.account)">
去登录
</ElLink>
</div>
</ElForm>
</template>
<style lang="scss" scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}
.el-form-item {
margin-bottom: 24px;
:deep(.el-input) {
width: 100%;
height: 48px;
line-height: inherit;
input {
height: 48px;
}
.el-input__prefix,
.el-input__suffix {
display: flex;
align-items: center;
}
.el-input__prefix {
left: 10px;
}
.el-input__suffix {
right: 10px;
}
}
}
</style>

View File

@ -38,7 +38,7 @@ function handleChange(index: number) {
<TabList class="inline-flex select-none items-center justify-center rounded-md bg-stone-1 p-1 ring-1 ring-stone-2 dark-bg-stone-9 dark-ring-stone-8">
<Tab v-for="(option, index) in options" :key="index" v-slot="{ selected }" as="template">
<button
class="w-full inline-flex items-center justify-center gap-1 break-keep border-size-0 rounded-md bg-inherit px-2 py-1.5 text-sm text-dark ring-stone-2 ring-inset dark-text-white focus-outline-none focus-ring-2 dark-ring-stone-8" :class="{
class="w-full inline-flex items-center justify-center gap-1 whitespace-nowrap border-size-0 rounded-md bg-inherit px-2 py-1.5 text-sm text-dark ring-stone-2 ring-inset dark-text-white focus-outline-none focus-ring-2 dark-ring-stone-8" :class="{
'cursor-default bg-white dark-bg-dark-9': selected,
'cursor-pointer opacity-50 hover-(opacity-100)': !selected,
}"

View File

@ -26,10 +26,13 @@ declare module 'vue' {
ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
ImagesUpload: typeof import('./../components/ImagesUpload/index.vue')['default']
ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']
LoginForm: typeof import('./../components/LoginForm/index.vue')['default']
NotAllowed: typeof import('./../components/NotAllowed/index.vue')['default']
PageHeader: typeof import('./../components/PageHeader/index.vue')['default']
PageMain: typeof import('./../components/PageMain/index.vue')['default']
PcasCascader: typeof import('./../components/PcasCascader/index.vue')['default']
RegisterForm: typeof import('./../components/RegisterForm/index.vue')['default']
ResetPasswordForm: typeof import('./../components/ResetPasswordForm/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SearchBar: typeof import('./../components/SearchBar/index.vue')['default']

View File

@ -6,11 +6,8 @@ meta:
</route>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import Copyright from '@/layouts/components/Copyright/index.vue'
import useSettingsStore from '@/store/modules/settings'
import useUserStore from '@/store/modules/user'
defineOptions({
name: 'Login',
@ -18,324 +15,67 @@ defineOptions({
const route = useRoute()
const router = useRouter()
const settingsStore = useSettingsStore()
const userStore = useUserStore()
const banner = new URL('../assets/images/login-banner.png', import.meta.url).href
const logo = new URL('../assets/images/logo.png', import.meta.url).href
const title = import.meta.env.VITE_APP_TITLE
// default qrcode
const loginType = ref('default')
// login register reset
const formType = ref('login')
const loading = ref(false)
const redirect = ref(route.query.redirect?.toString() ?? settingsStore.settings.home.fullPath)
//
const loginFormRef = ref<FormInstance>()
const loginForm = ref({
account: localStorage.login_account || '',
password: '',
remember: !!localStorage.login_account,
})
const loginRules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
password: [
{ required: true, trigger: 'blur', message: '请输入密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
})
function handleLogin() {
loginFormRef.value?.validate((valid) => {
if (valid) {
loading.value = true
userStore.login(loginForm.value).then(() => {
loading.value = false
if (loginForm.value.remember) {
localStorage.setItem('login_account', loginForm.value.account)
}
else {
localStorage.removeItem('login_account')
}
router.push(redirect.value)
}).catch(() => {
loading.value = false
})
}
})
}
//
const registerFormRef = ref<FormInstance>()
const registerForm = ref({
account: '',
captcha: '',
password: '',
checkPassword: '',
})
const registerRules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
captcha: [
{ required: true, trigger: 'blur', message: '请输入验证码' },
],
password: [
{ required: true, trigger: 'blur', message: '请输入密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
checkPassword: [
{ required: true, trigger: 'blur', message: '请再次输入密码' },
{
validator: (rule, value, callback) => {
if (value !== registerForm.value.password) {
callback(new Error('两次输入的密码不一致'))
}
else {
callback()
}
},
},
],
})
function handleRegister() {
ElMessage({
message: '注册模块仅提供界面演示,无实际功能,需开发者自行扩展',
type: 'warning',
})
registerFormRef.value?.validate((valid) => {
if (valid) {
//
}
})
}
//
const resetFormRef = ref<FormInstance>()
const resetForm = ref({
account: localStorage.login_account,
captcha: '',
newPassword: '',
})
const resetRules = ref<FormRules>({
account: [
{ required: true, trigger: 'blur', message: '请输入用户名' },
],
captcha: [
{ required: true, trigger: 'blur', message: '请输入验证码' },
],
newPassword: [
{ required: true, trigger: 'blur', message: '请输入新密码' },
{ min: 6, max: 18, trigger: 'blur', message: '密码长度为6到18位' },
],
})
function handleReset() {
ElMessage({
message: '重置密码仅提供界面演示,无实际功能,需开发者自行扩展',
type: 'info',
})
resetFormRef.value?.validate((valid) => {
if (valid) {
//
}
})
}
function testAccount(account: string) {
loginForm.value.account = account
loginForm.value.password = '123456'
handleLogin()
}
const account = ref<string>()
//
const formType = ref<'login' | 'register' | 'resetPassword'>('login')
const formRef = ref()
</script>
<template>
<div>
<div class="bg-banner" />
<div id="login-box">
<div class="login-banner">
<img :src="logo" class="logo">
<img :src="banner" class="banner">
</div>
<ElForm v-show="formType === 'login'" ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form">
<div class="mb-6">
<HTabList
v-model="loginType" :options="[
{ label: '账号密码登录', value: 'default' },
{ label: '扫码登录', value: 'qrcode' },
]"
/>
</div>
<template v-if="loginType === 'default'">
<div class="title-container">
<h3 class="title">
欢迎来到 {{ title }} ! 👋🏻
</h3>
</div>
<div>
<ElFormItem prop="account">
<ElInput v-model="loginForm.account" placeholder="用户名" type="text" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="password">
<ElInput v-model="loginForm.password" type="password" placeholder="密码" tabindex="2" autocomplete="new-password" show-password @keyup.enter="handleLogin">
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<div class="flex-bar">
<ElCheckbox v-model="loginForm.remember">
记住我
</ElCheckbox>
<ElLink type="primary" :underline="false" @click="formType = 'reset'">
忘记密码了?
</ElLink>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%;" @click.prevent="handleLogin">
登录
</ElButton>
<div class="sub-link">
<span class="text">还没有帐号?</span>
<ElLink type="primary" :underline="false" @click="formType = 'register'">
创建新帐号
</ElLink>
</div>
</template>
<template v-else-if="loginType === 'qrcode'">
<div class="flex flex-col items-center">
<el-image src="https://s2.loli.net/2024/04/26/GsahtuIZ9XOg5jr.png" class="h-[250px] w-[250px]" />
<div class="mt-2 op-50">
请使用微信扫码登录
</div>
</div>
</template>
<div style="margin-top: 20px; margin-bottom: -20px; text-align: center;">
<ElDivider>演示账号一键登录</ElDivider>
<ElButton type="primary" size="small" plain @click="testAccount('admin')">
admin
</ElButton>
<ElButton size="small" plain @click="testAccount('test')">
test
</ElButton>
</div>
</ElForm>
<ElForm v-show="formType === 'register'" ref="registerFormRef" :model="registerForm" :rules="registerRules" class="login-form" auto-complete="on">
<div class="title-container">
<h3 class="title">
探索从这里开始! 🚀
</h3>
</div>
<div>
<ElFormItem prop="account">
<ElInput v-model="registerForm.account" placeholder="用户名" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="captcha">
<ElInput v-model="registerForm.captcha" placeholder="验证码" tabindex="2">
<template #prefix>
<SvgIcon name="i-ic:baseline-verified-user" />
</template>
<template #append>
<ElButton>发送验证码</ElButton>
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="password">
<ElInput v-model="registerForm.password" type="password" placeholder="密码" tabindex="3" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="checkPassword">
<ElInput v-model="registerForm.checkPassword" type="password" placeholder="确认密码" tabindex="4" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%; margin-top: 20px;" @click.prevent="handleRegister">
注册
</ElButton>
<div class="sub-link">
<span class="text">已经有帐号?</span>
<ElLink type="primary" :underline="false" @click="formType = 'login'">
去登录
</ElLink>
</div>
</ElForm>
<ElForm v-show="formType === 'reset'" ref="resetFormRef" :model="resetForm" :rules="resetRules" class="login-form">
<div class="title-container">
<h3 class="title">
忘记密码了? 🔒
</h3>
</div>
<div>
<ElFormItem prop="account">
<ElInput v-model="resetForm.account" placeholder="用户名" type="text" tabindex="1">
<template #prefix>
<SvgIcon name="i-ri:user-3-fill" />
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="captcha">
<ElInput v-model="resetForm.captcha" placeholder="验证码" type="text" tabindex="2">
<template #prefix>
<SvgIcon name="i-ic:baseline-verified-user" />
</template>
<template #append>
<ElButton>发送验证码</ElButton>
</template>
</ElInput>
</ElFormItem>
<ElFormItem prop="newPassword">
<ElInput v-model="resetForm.newPassword" type="password" placeholder="新密码" tabindex="3" show-password>
<template #prefix>
<SvgIcon name="i-ri:lock-2-fill" />
</template>
</ElInput>
</ElFormItem>
</div>
<ElButton :loading="loading" type="primary" size="large" style="width: 100%; margin-top: 20px;" @click.prevent="handleReset">
确认
</ElButton>
<div class="sub-link">
<ElLink type="primary" :underline="false" @click="formType = 'login'">
去登录
</ElLink>
</div>
</ElForm>
<div class="bg-banner" />
<div class="login-box">
<div class="login-banner">
<img src="@/assets/images/logo.png" class="absolute left-4 top-4 h-30px rounded ring ring-stone-2 dark-ring-stone-8">
<img src="@/assets/images/login-banner.png" class="banner">
</div>
<div class="login-form flex-col-center">
<Transition name="fade" mode="out-in">
<LoginForm
v-if="formType === 'login'"
ref="formRef"
:account
@on-login="router.push(redirect)"
@on-register="(account) => { formType = 'register'; account = account }"
@on-reset-password="(account) => { formType = 'resetPassword'; account = account }"
/>
<RegisterForm
v-else-if="formType === 'register'"
ref="formRef"
:account
@on-register="(account) => { formType = 'login'; account = account }"
@on-login="formType = 'login'"
/>
<ResetPasswordForm
v-else-if="formType === 'resetPassword'"
ref="formRef"
:account
@on-reset-password="(account) => { formType = 'login'; account = account }"
@on-login="formType = 'login'"
/>
</Transition>
</div>
<Copyright />
</div>
<Copyright />
</template>
<style lang="scss" scoped>
.bg-banner {
position: fixed;
z-index: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at center, var(--g-container-bg), var(--g-bg));
}
[data-mode="mobile"] {
#login-box {
.login-box {
position: relative;
top: inherit;
left: inherit;
flex-direction: column;
justify-content: start;
width: 100%;
height: 100%;
border-radius: 0;
box-shadow: none;
transform: translateX(0) translateY(0);
.login-banner {
width: 100%;
@ -355,8 +95,6 @@ function testAccount(account: string) {
.login-form {
width: 100%;
min-height: auto;
padding: 30px;
}
}
@ -365,29 +103,19 @@ function testAccount(account: string) {
}
}
:deep(input[type="password"]::-ms-reveal) {
display: none;
}
.bg-banner {
position: fixed;
z-index: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at center, var(--g-container-bg), var(--g-bg));
}
#login-box {
.login-box {
position: absolute;
top: 50%;
left: 50%;
display: flex;
justify-content: space-between;
overflow: hidden;
background-color: var(--g-container-bg);
border-radius: 10px;
box-shadow: var(--el-box-shadow);
transform: translateX(-50%) translateY(-50%);
[data-mode="pc"] & {
top: 50%;
left: 50%;
border-radius: 10px;
box-shadow: var(--el-box-shadow);
transform: translateX(-50%) translateY(-50%);
}
.login-banner {
position: relative;
@ -400,88 +128,11 @@ function testAccount(account: string) {
@include position-center(y);
}
.logo {
position: absolute;
top: 20px;
left: 20px;
height: 30px;
border-radius: 4px;
box-shadow: var(--el-box-shadow-light);
}
}
.login-form {
display: flex;
flex-direction: column;
justify-content: center;
width: 500px;
min-height: 500px;
padding: 50px;
overflow: hidden;
.title-container {
position: relative;
.title {
margin: 0 auto 30px;
font-size: 1.3em;
font-weight: bold;
color: var(--el-text-color-primary);
}
}
}
.el-form-item {
margin-bottom: 24px;
:deep(.el-input) {
width: 100%;
height: 48px;
line-height: inherit;
input {
height: 48px;
}
.el-input__prefix,
.el-input__suffix {
display: flex;
align-items: center;
}
.el-input__prefix {
left: 10px;
}
.el-input__suffix {
right: 10px;
}
}
}
:deep(.el-divider__text) {
background-color: var(--g-container-bg);
}
.flex-bar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.sub-link {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
font-size: 14px;
color: var(--el-text-color-secondary);
.text {
margin-right: 10px;
}
transition: height 0.15s ease;
}
}
@ -492,4 +143,14 @@ function testAccount(account: string) {
padding: 20px;
margin: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.15s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>