mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-27 14:52:56 +00:00
chore: 清理冗余代码与配置,优化项目结构
1. 删除无用文件与废弃代码:移除locale枚举、element-plus插件、sse路由、api token模块等 2. 简化类型导入与依赖:移除大量未使用的类型导入,统一echarts导入方式 3. 优化配置与样式:调整gitignore、样式引入顺序,新增列表动画样式 4. 修复接口与模型:修正接口返回类型、查询参数配置,更新部门模型字段 5. 优化性能与体验:添加图片懒加载,优化加载逻辑与表格渲染 6. 调整环境配置:新增并更新开发/生产环境配置文件
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// 列表项入场动画
|
||||
// 使用 stagger 实现逐项淡入上移效果
|
||||
|
||||
// 单一项入场
|
||||
@keyframes fa-fade-in-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-slide-in-right {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 逐项动画混入 — 子项按 index 延迟入场
|
||||
// 使用方式:在列表容器上应用 .fa-stagger-enter
|
||||
.fa-stagger-enter {
|
||||
> * {
|
||||
animation: fa-fade-in-up 0.4s cubic-bezier(0.4, 0, 0.2, 1) both;
|
||||
}
|
||||
|
||||
@for $i from 1 through 20 {
|
||||
> *:nth-child(#{$i}) {
|
||||
animation-delay: #{$i * 0.05}s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 淡入类
|
||||
.fa-fade-enter {
|
||||
animation: fa-fade-in 0.3s ease both;
|
||||
}
|
||||
|
||||
// 右滑入类
|
||||
.fa-slide-right-enter {
|
||||
animation: fa-slide-in-right 0.35s cubic-bezier(0.4, 0, 0.2, 1) both;
|
||||
}
|
||||
|
||||
// Vue Transition 使用的类名
|
||||
.fa-list-enter-active {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.fa-list-leave-active {
|
||||
position: absolute; // 让离开动画不影响其他元素布局
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.fa-list-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
|
||||
.fa-list-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(-12px);
|
||||
}
|
||||
|
||||
.fa-list-move {
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
$bg-animation-color-light: #000;
|
||||
$bg-animation-color-dark: #fff;
|
||||
$bg-animation-duration: 0.5s;
|
||||
$bg-animation-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
html {
|
||||
--bg-animation-color: #{$bg-animation-color-light};
|
||||
@@ -10,13 +11,13 @@ html {
|
||||
--bg-animation-color: #{$bg-animation-color-dark};
|
||||
}
|
||||
|
||||
// View transition styles
|
||||
// View transition styles — 圆形展开/收拢过渡
|
||||
&::view-transition-old(*) {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
&::view-transition-new(*) {
|
||||
animation: clip $bg-animation-duration ease-in both;
|
||||
animation: clip $bg-animation-duration $bg-animation-easing both;
|
||||
}
|
||||
|
||||
&::view-transition-old(root) {
|
||||
@@ -29,7 +30,7 @@ html {
|
||||
|
||||
&.dark {
|
||||
&::view-transition-old(*) {
|
||||
animation: clip $bg-animation-duration ease-in reverse both;
|
||||
animation: clip $bg-animation-duration $bg-animation-easing reverse both;
|
||||
}
|
||||
|
||||
&::view-transition-new(*) {
|
||||
|
||||
@@ -366,11 +366,18 @@
|
||||
|
||||
// 表格按钮悬浮效果
|
||||
.hover-btn {
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
|
||||
filter: brightness(1.1);
|
||||
transform: translateY(-2px) scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: 0 2px 6px rgb(0 0 0 / 12%);
|
||||
transform: translateY(-1px) scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
// 去除移动端点击背景色
|
||||
@@ -379,3 +386,134 @@
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 全局空状态样式 ──
|
||||
.fa-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 240px;
|
||||
padding: 40px 20px;
|
||||
color: var(--fa-gray-500);
|
||||
|
||||
.fa-empty-state__icon {
|
||||
margin-bottom: 16px;
|
||||
font-size: 48px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.fa-empty-state__title {
|
||||
margin-bottom: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--fa-gray-600);
|
||||
}
|
||||
|
||||
.fa-empty-state__desc {
|
||||
font-size: 13px;
|
||||
color: var(--fa-gray-500);
|
||||
}
|
||||
}
|
||||
|
||||
// ── 全局加载骨架基础样式 ──
|
||||
.fa-skeleton-pulse {
|
||||
animation: fa-skeleton-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes fa-skeleton-pulse {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 错误重试样式 ──
|
||||
.fa-error-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 240px;
|
||||
padding: 40px 20px;
|
||||
text-align: center;
|
||||
|
||||
.fa-error-state__icon {
|
||||
margin-bottom: 16px;
|
||||
font-size: 48px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.fa-error-state__title {
|
||||
margin-bottom: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--fa-gray-700);
|
||||
}
|
||||
|
||||
.fa-error-state__desc {
|
||||
margin-bottom: 20px;
|
||||
font-size: 13px;
|
||||
color: var(--fa-gray-500);
|
||||
}
|
||||
|
||||
.fa-error-state__action {
|
||||
.el-button {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── 通用页面内容间距 ──
|
||||
.page-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
|
||||
@media (width <= 640px) {
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 表单内间距一致性 ──
|
||||
.form-section {
|
||||
margin-bottom: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-section__title {
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--fa-gray-800);
|
||||
border-bottom: 1px solid var(--fa-gray-200);
|
||||
}
|
||||
|
||||
// ── 统计卡片悬浮效果 ──
|
||||
.stat-card-hover {
|
||||
transition:
|
||||
transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
box-shadow:
|
||||
0 8px 24px rgb(0 0 0 / 6%),
|
||||
0 2px 8px rgb(0 0 0 / 3%);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* css3动画
|
||||
*
|
||||
* 动画 mixin(已简化,移除重复 keyframes)
|
||||
* @param {Map} $from 起始属性
|
||||
* @param {Map} $to 结束属性
|
||||
* @param {String} $name 动画名称
|
||||
*/
|
||||
@mixin animation(
|
||||
$from: (
|
||||
@@ -48,14 +50,8 @@
|
||||
$to: (
|
||||
width: 100px,
|
||||
),
|
||||
$name: mymove,
|
||||
$animate: mymove 2s 1 linear infinite
|
||||
$name: mymove
|
||||
) {
|
||||
-webkit-animation: $animate;
|
||||
-moz-animation: $animate;
|
||||
-o-animation: $animate;
|
||||
animation: $animate;
|
||||
|
||||
@keyframes #{$name} {
|
||||
from {
|
||||
@each $key, $value in $from {
|
||||
@@ -69,20 +65,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$name} {
|
||||
from {
|
||||
@each $key, $value in $from {
|
||||
$key: $value;
|
||||
}
|
||||
}
|
||||
|
||||
to {
|
||||
@each $key, $value in $to {
|
||||
$key: $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 圆形盒子
|
||||
@@ -118,7 +100,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
//背景透明,文字不透明。兼容IE8
|
||||
// 背景透明,文字不透明。兼容IE8
|
||||
@mixin betterTransparentize($color, $alpha) {
|
||||
$c: rgba($color, $alpha);
|
||||
$ie_c: ie_hex_str($c);
|
||||
@@ -131,7 +113,7 @@
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c});
|
||||
}
|
||||
|
||||
//添加浏览器前缀
|
||||
// 添加浏览器前缀
|
||||
@mixin browserPrefix($propertyName, $value) {
|
||||
@each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
|
||||
#{$prefix}#{$propertyName}: $value;
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/* 滚动条 */
|
||||
/* 滚动条优化 */
|
||||
|
||||
/* 滚动条整体部分,必须要设置 */
|
||||
::-webkit-scrollbar {
|
||||
width: 4px !important;
|
||||
height: 0 !important;
|
||||
width: 5px !important;
|
||||
height: 4px !important;
|
||||
}
|
||||
|
||||
/* 滚动条的轨道 */
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--fa-gray-200);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 滚动条的滑块按钮 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--theme-color) !important;
|
||||
border-radius: 5px;
|
||||
-webkit-transition: all 0.2s;
|
||||
background-clip: content-box;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
@@ -41,16 +42,20 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--default-bg-color);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: color-mix(in srgb, var(--theme-color) 60%, transparent) !important;
|
||||
background-color: color-mix(in srgb, var(--theme-color) 55%, transparent) !important;
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in srgb, var(--theme-color) 75%, transparent) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-scrollbar {
|
||||
--el-scrollbar-bg-color: color-mix(in srgb, var(--theme-color) 60%, transparent) !important;
|
||||
--el-scrollbar-hover-bg-color: color-mix(in srgb, var(--theme-color) 80%, black) !important;
|
||||
--el-scrollbar-bg-color: color-mix(in srgb, var(--theme-color) 55%, transparent) !important;
|
||||
--el-scrollbar-hover-bg-color: color-mix(
|
||||
in srgb,
|
||||
var(--theme-color) 75%,
|
||||
transparent
|
||||
) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,20 +127,37 @@ html.dark .el-card {
|
||||
border-radius: var(--el-border-radius-small) !important;
|
||||
}
|
||||
|
||||
// ── Dialog 优化 ──
|
||||
.el-dialog {
|
||||
overflow: hidden;
|
||||
border-radius: calc(var(--custom-radius) / 1.2 + 2px) !important;
|
||||
// 添加柔和的阴影层次感
|
||||
box-shadow:
|
||||
0 6px 30px rgb(0 0 0 / 8%),
|
||||
0 2px 8px rgb(0 0 0 / 4%) !important;
|
||||
|
||||
.el-dialog__header {
|
||||
padding: 16px 20px 8px !important;
|
||||
margin-right: 0 !important;
|
||||
border-bottom: 1px solid var(--fa-gray-200);
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog__header {
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
position: relative; // 为了兼容 el-pagination 样式,需要设置 relative,不然会影响 el-pagination 的样式,比如 el-pagination__jump--small 会被影响,导致 el-pagination__jump--small 按钮无法点击,详见 URL_ADDRESS.com/element-plus/element-plus/issues/5684#issuecomment-1176299275;
|
||||
padding: 12px 0 !important;
|
||||
padding: 20px !important;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding: 8px 20px 16px !important;
|
||||
border-top: 1px solid var(--fa-gray-200);
|
||||
}
|
||||
|
||||
.el-dialog.el-dialog-border {
|
||||
@@ -167,20 +184,34 @@ html.dark .el-card {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Drawer 优化 ──
|
||||
.el-drawer {
|
||||
box-shadow:
|
||||
-4px 0 24px rgb(0 0 0 / 6%),
|
||||
0 2px 8px rgb(0 0 0 / 4%) !important;
|
||||
}
|
||||
|
||||
.el-drawer__header {
|
||||
padding: 12px 8px !important;
|
||||
margin-bottom: 2px !important;
|
||||
padding: 16px 16px 12px !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-bottom: 1px solid var(--fa-gray-200);
|
||||
|
||||
.el-drawer__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.el-drawer__body {
|
||||
position: relative; // 为了兼容 el-pagination 样式,需要设置 relative,不然会影响 el-pagination 的样式,比如 el-pagination__jump--small 会被影响,导致 el-pagination__jump--small 按钮无法点击,详见 URL_ADDRESS.com/element-plus/element-plus/issues/5684#issuecomment-1176299275;
|
||||
padding: 0 8px !important;
|
||||
padding: 16px !important;
|
||||
}
|
||||
|
||||
// el-message 样式优化
|
||||
.el-message {
|
||||
background-color: var(--default-box-color) !important;
|
||||
border: 0 !important;
|
||||
border-radius: 8px !important;
|
||||
box-shadow:
|
||||
0 6px 16px 0 rgb(0 0 0 / 8%),
|
||||
0 3px 6px -4px rgb(0 0 0 / 12%),
|
||||
@@ -189,6 +220,23 @@ html.dark .el-card {
|
||||
p {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
// 成功/警告/错误等消息再加一点左边界标识色
|
||||
&.el-message--success {
|
||||
border-left: 3px solid var(--el-color-success) !important;
|
||||
}
|
||||
|
||||
&.el-message--warning {
|
||||
border-left: 3px solid var(--el-color-warning) !important;
|
||||
}
|
||||
|
||||
&.el-message--error {
|
||||
border-left: 3px solid var(--el-color-error) !important;
|
||||
}
|
||||
|
||||
&.el-message--info {
|
||||
border-left: 3px solid var(--el-color-info) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 修改 el-dropdown 样式
|
||||
@@ -196,6 +244,9 @@ html.dark .el-card {
|
||||
padding: 6px !important;
|
||||
border: none !important;
|
||||
border-radius: 10px !important;
|
||||
box-shadow:
|
||||
0 4px 16px rgb(0 0 0 / 8%),
|
||||
0 2px 8px rgb(0 0 0 / 4%) !important;
|
||||
|
||||
.el-dropdown-menu__item {
|
||||
padding: 6px 16px !important;
|
||||
@@ -252,6 +303,42 @@ html.dark .el-card {
|
||||
|
||||
// 修改el-button样式
|
||||
.el-button {
|
||||
// 按钮全局过渡
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
|
||||
&.el-button--default {
|
||||
&:not(.is-circle) {
|
||||
padding: 8px 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.el-button--primary {
|
||||
// 主按钮阴影层次
|
||||
box-shadow: 0 2px 6px rgb(var(--el-color-primary), 0.15);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgb(var(--el-color-primary), 0.25);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: 0 1px 3px rgb(var(--el-color-primary), 0.15);
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 小型按钮
|
||||
&.el-button--small {
|
||||
height: 28px !important;
|
||||
padding: 4px 12px !important;
|
||||
}
|
||||
|
||||
// 大型按钮
|
||||
&.el-button--large {
|
||||
height: 44px !important;
|
||||
padding: 12px 24px !important;
|
||||
}
|
||||
|
||||
&.el-button--text {
|
||||
padding: 0 !important;
|
||||
background-color: transparent !important;
|
||||
@@ -265,11 +352,26 @@ html.dark .el-card {
|
||||
// 修改el-tag样式
|
||||
.el-tag {
|
||||
font-weight: 500;
|
||||
border-radius: 4px !important;
|
||||
transition: all 0s !important;
|
||||
|
||||
&.el-tag--default {
|
||||
height: 26px !important;
|
||||
}
|
||||
|
||||
&.el-tag--small {
|
||||
height: 22px !important;
|
||||
padding: 0 6px !important;
|
||||
font-size: 11px !important;
|
||||
line-height: 22px !important;
|
||||
}
|
||||
|
||||
&.el-tag--large {
|
||||
height: 32px !important;
|
||||
padding: 0 12px !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 32px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-checkbox-group {
|
||||
@@ -346,8 +448,8 @@ html.dark .el-card {
|
||||
right: 7px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
transition: all 0.3s;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--fa-gray-900) !important;
|
||||
@@ -360,7 +462,7 @@ html.dark .el-card {
|
||||
}
|
||||
|
||||
.el-message-box__title {
|
||||
font-weight: 500 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.el-table__column-filter-trigger i {
|
||||
@@ -368,9 +470,11 @@ html.dark .el-card {
|
||||
color: var(--theme-color) !important;
|
||||
}
|
||||
|
||||
// 去除 el-dropdown 鼠标放上去出现的边框
|
||||
// 键盘焦点可见性:用自定义样式替代移除 outline
|
||||
.el-tooltip__trigger:focus-visible {
|
||||
outline: unset;
|
||||
outline: 2px solid var(--el-color-primary) !important;
|
||||
outline-offset: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
// ipad 表单右侧按钮优化
|
||||
@@ -382,13 +486,13 @@ html.dark .el-card {
|
||||
|
||||
.login-out-dialog {
|
||||
padding: 30px 20px !important;
|
||||
border-radius: 10px !important;
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
// 修改 dialog 动画
|
||||
// 修改 dialog 动画 - 更自然的弹性动画
|
||||
.dialog-fade-enter-active {
|
||||
.el-dialog:not(.is-draggable) {
|
||||
animation: dialog-open 0.3s cubic-bezier(0.32, 0.14, 0.15, 0.86);
|
||||
animation: dialog-open 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
// 修复 el-dialog 动画后宽度不自适应问题
|
||||
.el-select__selected-item {
|
||||
@@ -398,34 +502,34 @@ html.dark .el-card {
|
||||
}
|
||||
|
||||
.dialog-fade-leave-active {
|
||||
animation: fade-out 0.2s linear;
|
||||
animation: fade-out 0.2s ease-in;
|
||||
|
||||
.el-dialog:not(.is-draggable) {
|
||||
animation: dialog-close 0.5s;
|
||||
animation: dialog-close 0.25s ease-in forwards;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dialog-open {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.2);
|
||||
transform: scale(0.85) translateY(20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dialog-close {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0.2);
|
||||
transform: scale(0.9) translateY(10px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,9 +611,9 @@ html.dark .el-card {
|
||||
|
||||
// 优化树型菜单样式
|
||||
.el-tree-node__content {
|
||||
padding: 1px 0;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--fa-hover-color) !important;
|
||||
@@ -522,11 +626,12 @@ html.dark .el-card {
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏折叠菜单弹窗 hover 出现的边框
|
||||
// 折叠菜单弹窗:移除默认边框但保留键盘焦点可见性
|
||||
.menu-left-popper:focus-within,
|
||||
.horizontal-menu-popper:focus-within {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: 2px solid var(--el-color-primary) !important;
|
||||
outline-offset: -2px;
|
||||
border-radius: var(--el-border-radius-base);
|
||||
}
|
||||
|
||||
// 数字输入组件右侧按钮高度跟随自定义组件高度
|
||||
@@ -536,3 +641,181 @@ html.dark .el-card {
|
||||
height: calc((var(--el-component-size) / 2)) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElTable 表格样式优化 ──
|
||||
.el-table {
|
||||
// 表格行圆角 + 悬停高亮
|
||||
.el-table__body tr.el-table__row {
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover > td.el-table__cell {
|
||||
background-color: var(--fa-hover-color) !important;
|
||||
}
|
||||
|
||||
// 当前行高亮
|
||||
&.current-row > td.el-table__cell {
|
||||
background-color: color-mix(in srgb, var(--el-color-primary) 8%, transparent) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 斑马纹优化
|
||||
&.el-table--striped .el-table__body tr.el-table__row--striped {
|
||||
td.el-table__cell {
|
||||
background-color: var(--fa-gray-100);
|
||||
}
|
||||
|
||||
&:hover td.el-table__cell {
|
||||
background-color: var(--fa-hover-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 表头样式
|
||||
.el-table__header-wrapper {
|
||||
th.el-table__cell {
|
||||
font-weight: 600;
|
||||
color: var(--fa-gray-700);
|
||||
background-color: var(--fa-gray-100);
|
||||
}
|
||||
}
|
||||
|
||||
// 单元格垂直居中
|
||||
.el-table__cell {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
|
||||
// 空状态卡片样式
|
||||
.el-table__empty-block {
|
||||
min-height: 200px;
|
||||
|
||||
.el-empty {
|
||||
.el-empty__image {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.el-empty__description {
|
||||
p {
|
||||
font-size: 13px;
|
||||
color: var(--fa-gray-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElSwitch 开关优化 ──
|
||||
.el-switch {
|
||||
--el-switch-off-color: var(--fa-gray-400);
|
||||
|
||||
&.is-checked {
|
||||
.el-switch__core {
|
||||
box-shadow: 0 0 6px rgb(var(--el-color-primary), 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.el-switch__core {
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElInput 输入框优化 ──
|
||||
.el-input--default {
|
||||
.el-input__wrapper {
|
||||
box-shadow: 0 0 0 1px var(--default-border) inset !important;
|
||||
transition: box-shadow 0.25s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 1px var(--fa-gray-500) inset !important;
|
||||
}
|
||||
|
||||
&.is-focus {
|
||||
box-shadow: 0 0 0 1px var(--el-color-primary) inset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElCard 卡片优化 ──
|
||||
.el-card {
|
||||
transition:
|
||||
box-shadow 0.25s ease,
|
||||
transform 0.25s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow:
|
||||
0 4px 20px rgb(0 0 0 / 4%),
|
||||
0 1px 4px rgb(0 0 0 / 2%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElCollapse 折叠面板优化 ──
|
||||
.el-collapse-item__header {
|
||||
font-weight: 500;
|
||||
transition: color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElStep 步骤条优化 ──
|
||||
.el-step__title {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.el-step__head.is-finish {
|
||||
color: var(--el-color-primary) !important;
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
// ── ElDivider 分割线优化 ──
|
||||
.el-divider--horizontal {
|
||||
margin: 16px 0 !important;
|
||||
}
|
||||
|
||||
.el-divider__text {
|
||||
font-size: 12px !important;
|
||||
color: var(--fa-gray-500) !important;
|
||||
}
|
||||
|
||||
// ── ElAlert 警告优化 ──
|
||||
.el-alert {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px !important;
|
||||
|
||||
&.el-alert--info {
|
||||
border-color: color-mix(in srgb, var(--el-color-info) 20%, transparent);
|
||||
}
|
||||
|
||||
&.el-alert--success {
|
||||
border-color: color-mix(in srgb, var(--el-color-success) 20%, transparent);
|
||||
}
|
||||
|
||||
&.el-alert--warning {
|
||||
border-color: color-mix(in srgb, var(--el-color-warning) 20%, transparent);
|
||||
}
|
||||
|
||||
&.el-alert--error {
|
||||
border-color: color-mix(in srgb, var(--el-color-error) 20%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
// ── ElDescriptions 描述列表优化 ──
|
||||
.el-descriptions__title {
|
||||
font-size: 15px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.el-descriptions__label {
|
||||
font-weight: 500 !important;
|
||||
color: var(--fa-gray-600) !important;
|
||||
}
|
||||
|
||||
// ── ElResult 结果页优化 ──
|
||||
.el-result__title {
|
||||
font-size: 18px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.el-result__sub-title {
|
||||
font-size: 13px !important;
|
||||
color: var(--fa-gray-500) !important;
|
||||
}
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
@use "./animations/router-transition";
|
||||
@use "./animations/theme-change";
|
||||
@use "./animations/theme-animation";
|
||||
@use "./animations/list-animation";
|
||||
|
||||
@@ -51,6 +51,15 @@
|
||||
--color-g-700: var(--fa-gray-700);
|
||||
--color-g-800: var(--fa-gray-800);
|
||||
--color-g-900: var(--fa-gray-900);
|
||||
|
||||
/* Font Size Configuration */
|
||||
--font-size-xs: 11px;
|
||||
--font-size-sm: 12px;
|
||||
--font-size-base: 13px;
|
||||
--font-size-lg: 15px;
|
||||
--font-size-xl: 18px;
|
||||
--font-size-2xl: 22px;
|
||||
--font-size-3xl: 28px;
|
||||
}
|
||||
|
||||
/* ==================== Custom Border Radius Utilities ==================== */
|
||||
@@ -62,11 +71,6 @@
|
||||
border-radius: calc(var(--custom-radius) / 2 + 2px);
|
||||
}
|
||||
|
||||
/* ==================== Flex Shortcut Utilities ====================
|
||||
* 解决项目里大量重复的 flex 居中 / 两端对齐 / 列布局组合(详见
|
||||
* scripts/find-tailwind-candidates.py 统计结果)。
|
||||
* 在模板里直接 class="flex-cc gap-2" 比 class="flex items-center justify-center gap-2" 短 60%。
|
||||
*/
|
||||
/* ==================== Custom Utility Classes ==================== */
|
||||
@layer utilities {
|
||||
/* Flexbox Layout Utilities */
|
||||
@@ -103,31 +107,102 @@
|
||||
@apply transition-all duration-300;
|
||||
}
|
||||
|
||||
/* Hover Lift Effect */
|
||||
.hover-lift {
|
||||
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Text Truncate */
|
||||
.text-truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Border Utilities */
|
||||
.border-full-d {
|
||||
@apply border border-[var(--default-border)];
|
||||
@apply border border-(--default-border);
|
||||
}
|
||||
|
||||
.border-b-d {
|
||||
@apply border-b border-[var(--default-border)];
|
||||
@apply border-b border-(--default-border);
|
||||
}
|
||||
|
||||
.border-t-d {
|
||||
@apply border-t border-[var(--default-border)];
|
||||
@apply border-t border-(--default-border);
|
||||
}
|
||||
|
||||
.border-l-d {
|
||||
@apply border-l border-[var(--default-border)];
|
||||
@apply border-l border-(--default-border);
|
||||
}
|
||||
|
||||
.border-r-d {
|
||||
@apply border-r border-[var(--default-border)];
|
||||
@apply border-r border-(--default-border);
|
||||
}
|
||||
|
||||
/* Cursor Utilities */
|
||||
.c-p {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
/* Gap utility aliases for consistency */
|
||||
.gap-xs {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.gap-sm {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.gap-md {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.gap-lg {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.gap-xl {
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
/* Text Color Shortcuts */
|
||||
.text-secondary {
|
||||
color: var(--fa-gray-500);
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: var(--fa-gray-400);
|
||||
}
|
||||
|
||||
/* Background Color Shortcuts */
|
||||
.bg-subtle {
|
||||
background-color: var(--fa-gray-100);
|
||||
}
|
||||
|
||||
.bg-hover {
|
||||
background-color: var(--fa-hover-color);
|
||||
}
|
||||
|
||||
/* Scrollable container (overflow auto, hidden scrollbar) */
|
||||
.scrollable-y {
|
||||
overflow: auto hidden;
|
||||
scrollbar-color: var(--fa-gray-300) transparent;
|
||||
scrollbar-width: thin;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--fa-gray-300);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Light Mode Variables ==================== */
|
||||
|
||||
Reference in New Issue
Block a user