mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-10-04 09:10:59 +00:00
chore: 完成多批次代码优化与重构
- 重构工作流模块目录结构,迁移代码文件 - 修复类型断言空值安全问题,添加 ! 操作符 - 优化样式类名,替换 flex-cc 为标准 flex 工具类 - 更新路由标签简化文案,移除冗余注释 - 调整 ruff 配置,放宽行长度限制 - 更新 README 与多语言文案,优化项目描述 - 修复表单、图表组件的类型与样式问题 - 简化搜索表单、数据卡片的布局代码
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="page-content border-0! bg-transparent! min-h-screen flex-cc">
|
||||
<div class="flex-cc max-md:block! max-md:text-center">
|
||||
<div class="page-content border-0! bg-transparent! min-h-screen flex items-center justify-center">
|
||||
<div class="flex items-center justify-center max-md:block! max-md:text-center">
|
||||
<FaThemeSvg :src="data.imgUrl" size="100%" class="w-100!" />
|
||||
<div class="ml-15 w-75 max-md:mx-auto max-md:mt-10 max-md:w-full max-md:text-center">
|
||||
<p class="text-xl leading-7 text-g-600 max-md:text-lg">{{ data.desc }}</p>
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
/**
|
||||
* 登录根布局
|
||||
* - 顶栏 fixed 透明叠在页面上(不占一条实体顶区);仅插画列 / 表单区随布局切换
|
||||
* - left / right:插画列与表单列横向排列(约 65% / 35%)
|
||||
* - center:全宽 + 视口级背景;登录卡居中、阴影高亮
|
||||
*/
|
||||
.login-auth-split {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.login-auth-split__col--illustration {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.login-auth-split__col--form {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 横向:插画 ~65%,表单列占剩余 */
|
||||
.login-auth-split--left,
|
||||
.login-auth-split--right {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.login-auth-split--left .login-auth-split__col--illustration,
|
||||
.login-auth-split--right .login-auth-split__col--illustration {
|
||||
flex: 0 0 65%;
|
||||
}
|
||||
|
||||
.login-auth-split--left .login-auth-split__col--form,
|
||||
.login-auth-split--right .login-auth-split__col--form {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.login-auth-split--left {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
@media only screen and (width <= 1600px) {
|
||||
.login-auth-split--left .login-auth-split__col--illustration,
|
||||
.login-auth-split--right .login-auth-split__col--illustration {
|
||||
flex: 0 0 60%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 居中模式:仅一列表单壳占满屏宽 */
|
||||
.login-auth-split--center {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.login-auth-split--center .login-auth-split__col--form {
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 顶栏与页脚之间的区域:纵向居中承载登录卡 */
|
||||
.login-auth-split--center .login-page-panel__scroll.login-page-panel__scroll--centered {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 0;
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
|
||||
/* 盖过 Tailwind overflow-y-auto:仅卡片内滚动,外层不出滚动条 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-page-panel__scroll--centered .login-panel-align-row {
|
||||
flex: 0 1 auto;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
/* 悬浮卡片:玻璃拟态,圆角透明 */
|
||||
.login-auth-split--center .auth-right-wrap {
|
||||
width: min(480px, calc(100vw - 2rem)) !important;
|
||||
max-width: min(480px, calc(100vw - 2rem));
|
||||
height: auto;
|
||||
max-height: calc(100dvh - 8rem);
|
||||
padding: 1.25rem 1.75rem;
|
||||
overflow: hidden auto;
|
||||
background: color-mix(in srgb, var(--el-bg-color) 72%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--el-border-color-lighter) 60%, transparent);
|
||||
border-radius: 20px;
|
||||
box-shadow:
|
||||
0 1px 8px rgb(15 23 42 / 5%),
|
||||
0 0 16px color-mix(in srgb, var(--el-color-primary) 6%, transparent);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.login-auth-split--center .auth-right-wrap .form {
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
html.dark .login-auth-split--center .auth-right-wrap {
|
||||
background: color-mix(in srgb, var(--el-bg-color) 55%, transparent);
|
||||
border-color: rgb(255 255 255 / 8%);
|
||||
box-shadow:
|
||||
0 1px 8px rgb(0 0 0 / 18%),
|
||||
0 0 16px color-mix(in srgb, var(--el-color-primary) 10%, transparent);
|
||||
}
|
||||
|
||||
/* 居中模式下页脚弱化,减少「分区后台」感 */
|
||||
.login-page-footer--floating-layout {
|
||||
border-top-color: color-mix(in srgb, var(--el-border-color-lighter) 55%, transparent);
|
||||
}
|
||||
|
||||
html.dark .login-page-footer--floating-layout {
|
||||
border-top-color: rgb(255 255 255 / 8%);
|
||||
}
|
||||
|
||||
/* 居中模式 footer 单行展示 */
|
||||
.login-auth-split--center .login-page-footer--floating-layout {
|
||||
.login-footer-text {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.login-footer-row {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.login-footer-row + .login-footer-row {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.login-footer-sep-center {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 1180px) {
|
||||
.login-auth-split {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.login-auth-split__col--illustration {
|
||||
flex: 0 0 auto !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.login-auth-split__col--form {
|
||||
flex: 1 1 auto !important;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 窄屏横排切竖排:恢复插画;居中模式本身无插画,不受影响 */
|
||||
.login-auth-split--center .auth-right-wrap {
|
||||
width: min(420px, calc(100vw - 1.5rem)) !important;
|
||||
max-width: min(420px, calc(100vw - 1.5rem));
|
||||
max-height: calc(100dvh - 6rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* 授权页表单区域(左右分栏时) */
|
||||
.auth-right-wrap {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 440px;
|
||||
height: 670px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
overflow: hidden;
|
||||
animation: slideInRight 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
||||
|
||||
@media (width <= 640px) {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 10rem);
|
||||
padding-right: 1.75rem;
|
||||
padding-left: 1.75rem;
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.form {
|
||||
height: 100%;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 2.5rem;
|
||||
color: var(--fa-gray-900);
|
||||
|
||||
@media (width <= 768px) {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
|
||||
@media (width <= 640px) {
|
||||
padding-top: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
margin-top: 10px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: var(--fa-gray-600);
|
||||
}
|
||||
|
||||
.custom-height {
|
||||
height: 40px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.login-page-panel {
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
html.dark .login-page-panel {
|
||||
.text-g-800 {
|
||||
color: rgb(255 255 255 / 78%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.login-page-form {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.login-page-form .el-form-item {
|
||||
margin-bottom: 1.1rem;
|
||||
}
|
||||
|
||||
.el-select__wrapper {
|
||||
min-height: 42px !important;
|
||||
}
|
||||
|
||||
.login-secondary-actions .login-secondary-btn {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
.login-page-form .el-input__wrapper {
|
||||
background-color: rgb(255 255 255 / 6%) !important;
|
||||
box-shadow: 0 0 0 1px rgb(255 255 255 / 10%) inset !important;
|
||||
}
|
||||
|
||||
.login-page-form .el-input__inner {
|
||||
color: rgb(255 255 255 / 92%);
|
||||
}
|
||||
|
||||
.login-page-form .el-input__inner::placeholder {
|
||||
color: rgb(255 255 255 / 35%);
|
||||
}
|
||||
|
||||
.login-page-form .el-select .el-select__wrapper {
|
||||
background-color: rgb(255 255 255 / 6%) !important;
|
||||
box-shadow: 0 0 0 1px rgb(255 255 255 / 10%) inset !important;
|
||||
}
|
||||
|
||||
.login-page-form .el-select__placeholder {
|
||||
color: rgb(255 255 255 / 40%);
|
||||
}
|
||||
|
||||
.login-page-form .el-select__selected-item {
|
||||
color: rgb(255 255 255 / 92%);
|
||||
}
|
||||
|
||||
.login-remember .el-checkbox__label {
|
||||
color: rgb(255 255 255 / 65%);
|
||||
}
|
||||
|
||||
.login-secondary-btn {
|
||||
color: rgb(255 255 255 / 85%) !important;
|
||||
background: transparent !important;
|
||||
border-color: rgb(255 255 255 / 22%) !important;
|
||||
border-radius: 8px;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary) !important;
|
||||
background: var(--el-color-primary-light-9) !important;
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.login-secondary-actions .login-secondary-btn {
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-page-footer {
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
|
||||
.login-footer-text {
|
||||
line-height: 1.65;
|
||||
color: var(--el-text-color-secondary) !important;
|
||||
}
|
||||
|
||||
.login-footer-row {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.login-footer-row + .login-footer-row {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.login-footer-sep-center {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login-page-footer__link {
|
||||
color: var(--el-text-color-regular);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.login-page-footer__sep {
|
||||
margin: 0 0.35rem;
|
||||
color: var(--el-border-color);
|
||||
}
|
||||
|
||||
.login-page-footer__record {
|
||||
display: inline-block;
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
html.dark .login-page-footer {
|
||||
border-top-color: rgb(255 255 255 / 8%);
|
||||
|
||||
.login-footer-text {
|
||||
color: rgb(255 255 255 / 42%) !important;
|
||||
}
|
||||
|
||||
.login-page-footer__link {
|
||||
color: rgb(255 255 255 / 48%);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.login-page-footer__sep {
|
||||
color: rgb(255 255 255 / 25%);
|
||||
}
|
||||
|
||||
.login-page-footer__record {
|
||||
color: rgb(255 255 255 / 35%);
|
||||
}
|
||||
}
|
||||
|
||||
.login-mobile-otp-cell {
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
max-width: 48px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
text-align: center;
|
||||
appearance: none;
|
||||
outline: none;
|
||||
background: var(--el-fill-color-blank);
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 8px;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--el-color-primary);
|
||||
box-shadow: 0 0 0 1px var(--el-color-primary) inset;
|
||||
}
|
||||
}
|
||||
|
||||
.login-mobile-sms-btn {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.login-mobile-actions {
|
||||
.el-button + .el-button {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.login-qr-card {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
.login-mobile-otp-cell {
|
||||
background: rgb(255 255 255 / 6%);
|
||||
border-color: rgb(255 255 255 / 14%);
|
||||
|
||||
&:focus {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -101,7 +101,7 @@
|
||||
<div class="login-form-tail flex flex-col gap-[1.1rem]">
|
||||
<div class="relative pb-3">
|
||||
<div
|
||||
class="relative z-2 overflow-hidden select-none rounded-lg border border-transparent tad-300"
|
||||
class="relative z-2 overflow-hidden select-none rounded-lg border border-transparent transition duration-300"
|
||||
:class="{ 'border-[#FF4E4F]!': !isPassing && isClickPass }"
|
||||
>
|
||||
<FaDragVerify
|
||||
@@ -116,14 +116,14 @@
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="absolute top-0 z-1 mt-2 px-px text-xs text-[#f56c6c] tad-300"
|
||||
class="absolute top-0 z-1 mt-2 px-px text-xs text-[#f56c6c] transition duration-300"
|
||||
:class="{ 'translate-y-10': !isPassing && isClickPass }"
|
||||
>
|
||||
{{ $t("login.placeholder.slider") }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="login-options-row flex-cb text-sm">
|
||||
<div class="login-options-row flex items-center justify-between text-sm">
|
||||
<ElCheckbox v-model="loginForm.remember" class="login-remember">
|
||||
{{ $t("login.rememberPwd") }}
|
||||
</ElCheckbox>
|
||||
@@ -231,5 +231,5 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@styles/custom/fa-login";
|
||||
@use "../fa-login";
|
||||
</style>
|
||||
+1
-1
@@ -122,5 +122,5 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@styles/custom/fa-login";
|
||||
@use "../fa-login";
|
||||
</style>
|
||||
+1
-1
@@ -203,5 +203,5 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@styles/custom/fa-login";
|
||||
@use "../fa-login";
|
||||
</style>
|
||||
+1
-1
@@ -72,5 +72,5 @@ const qrPayload = computed(() => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@styles/custom/fa-login";
|
||||
@use "../fa-login";
|
||||
</style>
|
||||
+1
-1
@@ -144,5 +144,5 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@styles/custom/fa-login";
|
||||
@use "../fa-login";
|
||||
</style>
|
||||
+13
-9
@@ -16,16 +16,16 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="auth-top-bar-actions-panel pointer-events-auto flex shrink-0 flex-cc gap-1.5 px-2 py-1.5 max-sm:mr-1"
|
||||
class="auth-top-bar-actions-panel pointer-events-auto flex shrink-0 flex items-center justify-center gap-1.5 px-2 py-1.5 max-sm:mr-1"
|
||||
>
|
||||
<div class="color-picker-expandable relative flex-c max-sm:hidden!">
|
||||
<div class="color-picker-expandable relative flex items-center max-sm:hidden!">
|
||||
<div
|
||||
class="color-dots absolute right-0 rounded-full flex-c gap-2 rounded-5 px-2.5 py-2 pr-9 pl-2.5 opacity-0"
|
||||
class="color-dots absolute right-0 rounded-full flex items-center gap-2 rounded-5 px-2.5 py-2 pr-9 pl-2.5 opacity-0"
|
||||
>
|
||||
<div
|
||||
v-for="(_color, index) in mainColors"
|
||||
:key="_color"
|
||||
class="color-dot relative size-5 c-p flex-cc rounded-full opacity-0"
|
||||
class="color-dot relative size-5 cursor-pointer flex items-center justify-center rounded-full opacity-0"
|
||||
:class="{ active: _color === systemThemeColor }"
|
||||
:style="{ background: _color, '--index': index }"
|
||||
@click="changeThemeColor(_color)"
|
||||
@@ -33,7 +33,9 @@
|
||||
<FaSvgIcon v-if="_color === systemThemeColor" icon="ri:check-fill" class="text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn palette-btn auth-top-bar__action relative z-2 h-8 w-8 c-p flex-cc tad-300">
|
||||
<div
|
||||
class="btn palette-btn auth-top-bar__action relative z-2 h-8 w-8 cursor-pointer flex items-center justify-center transition duration-300"
|
||||
>
|
||||
<FaSvgIcon icon="ri:palette-line" class="text-xl transition-colors duration-300" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,7 +45,7 @@
|
||||
popper-class="langDropDownStyle"
|
||||
>
|
||||
<div
|
||||
class="btn layout-align-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300"
|
||||
class="btn layout-align-btn auth-top-bar__action h-8 w-8 cursor-pointer flex items-center justify-center transition duration-300"
|
||||
:title="$t('login.panelAlign.label')"
|
||||
>
|
||||
<FaSvgIcon
|
||||
@@ -71,7 +73,9 @@
|
||||
@command="changeLanguage"
|
||||
popper-class="langDropDownStyle"
|
||||
>
|
||||
<div class="btn language-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300">
|
||||
<div
|
||||
class="btn language-btn auth-top-bar__action h-8 w-8 cursor-pointer flex items-center justify-center transition duration-300"
|
||||
>
|
||||
<FaSvgIcon
|
||||
icon="ri:translate-2"
|
||||
class="text-[19px] text-g-800 transition-colors duration-300"
|
||||
@@ -93,7 +97,7 @@
|
||||
</ElDropdown>
|
||||
<div
|
||||
v-if="shouldShowThemeToggle"
|
||||
class="btn theme-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300"
|
||||
class="btn theme-btn auth-top-bar__action h-8 w-8 cursor-pointer flex items-center justify-center transition duration-300"
|
||||
@click="themeAnimation"
|
||||
>
|
||||
<FaSvgIcon
|
||||
@@ -115,7 +119,7 @@ import { themeAnimation } from "@utils";
|
||||
import { languageOptions } from "@/locales";
|
||||
import { LanguageEnum } from "@/enums/appEnum";
|
||||
import AppConfig from "@/config";
|
||||
import { LoginPanelAlign } from "@/components/views/fa-login/useLoginPanelAlign";
|
||||
import { LoginPanelAlign } from "@/components/views/fa-login/composables/useLoginPanelAlign";
|
||||
|
||||
defineOptions({ name: "AuthTopBar" });
|
||||
|
||||
Reference in New Issue
Block a user