refactor(frontend): 重构前端样式体系,统一资源路径与代码规范

1.  重构SCSS样式结构,将原有分散的样式文件整合到custom目录下,统一使用@use替代@import
2.  删除冗余的全局样式文件,将样式逻辑内联到对应组件或集中到core目录
3.  新增DOMPurify依赖,对富文本内容添加XSS防护
4.  修复metrics端点暴露的兼容性问题,优化启动banner样式
5.  移除无用的权限校验代码,重构工作流组件路径与命名
6.  优化样式混合宏与响应式布局,修复部分组件样式冲突
This commit is contained in:
zhangtao
2026-06-01 00:58:21 +08:00
parent c2135bb456
commit c0733d9861
50 changed files with 1880 additions and 1792 deletions
+9
View File
@@ -302,6 +302,15 @@
transform: none !important;
}
// 表格按钮悬浮效果
.hover-btn {
&:hover {
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
filter: brightness(1.1);
transform: translateY(-2px) scale(1.05);
}
}
// 去除移动端点击背景色
@media screen and (width <= 1180px) {
* {
-18
View File
@@ -1,18 +0,0 @@
// CRUD 页面通用样式
// 从各 module_system 视图文件中提取的重复样式
// FaForm 在 Dialog 中的布局优化:隐藏最后一列操作按钮、内容区域自适应宽度
.crud-dialog-art-form {
:deep(.el-row > .el-col:last-child) {
display: none;
}
:deep(.el-form-item__content) {
max-width: 100%;
}
}
// 表格操作列按钮垂直居中
:deep(.inline-flex) {
vertical-align: middle;
}
@@ -1,40 +0,0 @@
// https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/common/var.scss
// 自定义Element 亮色主题
@forward "element-plus/theme-chalk/src/common/var.scss" with (
$colors: (
"white": #ffffff,
"black": #000000,
"primary": (
"base": #4080FF,
),
"success": (
"base": #13deb9,
),
"warning": (
"base": #ffae1f,
),
"danger": (
"base": #ff4d4f,
),
"error": (
"base": #fa896b,
),
"info": (
"base": #909399,
),
),
$button: (
"hover-bg-color": var(--el-color-primary-light-9),
"hover-border-color": var(--el-color-primary),
"border-color": var(--el-color-primary),
"text-color": var(--el-color-primary),
),
$messagebox: (
"border-radius": "12px",
),
$popover: (
"padding": "14px",
"border-radius": "10px",
)
);
+41 -3
View File
@@ -55,7 +55,6 @@
-o-animation: $animate;
animation: $animate;
/* stylelint-disable-next-line at-rule-prelude-no-invalid */
@keyframes #{$name} {
from {
@each $key, $value in $from {
@@ -69,6 +68,20 @@
}
}
}
@keyframes #{$name} {
from {
@each $key, $value in $from {
$key: $value;
}
}
to {
@each $key, $value in $to {
$key: $value;
}
}
}
}
// 圆形盒子
@@ -83,13 +96,18 @@
// placeholder
@mixin placeholder($color: #bbb) {
// Firefox
&::placeholder {
color: $color;
opacity: 1;
}
// Safari and Chrome (legacy)
/* stylelint-disable-next-line selector-no-vendor-prefix */
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $color;
}
@@ -99,6 +117,26 @@
}
}
//背景透明,文字不透明。兼容IE8
@mixin betterTransparentize($color, $alpha) {
$c: rgba($color, $alpha);
$ie_c: ie_hex_str($c);
zoom: 1;
background: rgba($color, 1);
background: $c;
background: transparent \9;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c})";
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;
}
}
// 边框
@mixin border($color: red) {
border: 1px solid $color;
@@ -6,6 +6,10 @@ $bg-animation-duration: 0.5s;
html {
--bg-animation-color: #{$bg-animation-color-light};
&.dark {
--bg-animation-color: #{$bg-animation-color-dark};
}
// View transition styles
&::view-transition-old(*) {
animation: none;
@@ -24,8 +28,6 @@ html {
}
&.dark {
--bg-animation-color: #{$bg-animation-color-dark};
&::view-transition-old(*) {
animation: clip $bg-animation-duration ease-in reverse both;
}
@@ -0,0 +1,53 @@
/**
* Element Plus 功能性颜色覆写 CSS 变量。
*
* 默认主色请与 src/config/setting.ts 中 themeColorPresets 首项保持一致。
*
* 注意:primary 颜色由运行时 setElementThemeColor() 动态写入,此处只覆写
* success / warning / danger / error / info 等编译期确定的功能性颜色。
* 这些变量无法通过 SCSS `@forward ... with()` 传递到 Element Plus 组件编译链,
* 因为 Dart Sass 模块隔离机制下 Element Plus 组件内部 `@use 'common/var'` 获得的是独立模块实例。
*/
@use "sass:map";
@use "element-plus/theme-chalk/src/common/var.scss" as ep with (
$colors: (
"white": #ffffff,
"black": #000000,
"primary": (
"base": #4080ff,
),
"success": (
"base": #13deb9,
),
"warning": (
"base": #ffae1f,
),
"danger": (
"base": #ff4d4f,
),
"error": (
"base": #fa896b,
),
"info": (
"base": #909399,
),
)
);
:root {
@each $type in (success, warning, danger, error, info) {
--el-color-#{$type}: #{map.get(ep.$colors, $type, "base")} !important;
@each $i in (3, 5, 7, 8, 9) {
--el-color-#{$type}-light-#{$i}: #{map.get(ep.$colors, $type, "light-#{$i}")} !important;
}
--el-color-#{$type}-dark-2: #{map.get(ep.$colors, $type, "dark-2")} !important;
}
}
/** 暗黑主题 */
html.dark {
--el-color-primary: #{map.get(ep.$colors, "primary", "base")} !important;
}
@@ -0,0 +1,412 @@
/**
* 登录根布局
* - 顶栏 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-bottom: 0;
/* 盖过 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%;
}
/* 悬浮卡片:居中模式尺寸与原先一致(520 宽、720/视口上限),无边框 + 主色高亮阴影 */
.login-auth-split--center .auth-right-wrap {
width: min(520px, calc(100vw - 2rem)) !important;
max-width: min(520px, calc(100vw - 2rem));
height: auto;
max-height: calc(100dvh - 6.5rem);
padding: 1.75rem 2rem 2rem;
overflow: hidden auto;
background-color: var(--el-bg-color);
border: none;
border-radius: 16px;
box-shadow:
0 6px 20px rgb(15 23 42 / 9%),
0 14px 36px rgb(15 23 42 / 10%),
0 0 18px color-mix(in srgb, var(--el-color-primary) 16%, transparent),
0 0 32px color-mix(in srgb, var(--el-color-primary) 7%, transparent);
}
.login-auth-split--center .auth-right-wrap .form {
height: auto;
min-height: 0;
padding-top: 1rem;
padding-bottom: 1rem;
}
html.dark .login-auth-split--center .auth-right-wrap {
border: none;
box-shadow:
0 8px 28px rgb(0 0 0 / 42%),
0 16px 44px rgb(0 0 0 / 46%),
0 0 22px color-mix(in srgb, var(--el-color-primary) 20%, transparent),
0 0 36px color-mix(in srgb, var(--el-color-primary) 9%, 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%);
}
@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(520px, calc(100vw - 1.5rem)) !important;
max-width: min(520px, calc(100vw - 1.5rem));
max-height: calc(100dvh - 6rem);
}
}
/* 授权页表单区域(左右分栏时) */
.auth-right-wrap {
position: relative;
flex-shrink: 0;
width: 440px;
height: 720px;
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: 40px;
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-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;
margin-left: 0.35rem;
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);
}
}
}
-189
View File
@@ -1,189 +0,0 @@
@reference '@styles/core/tailwind.css';
/**
* 登录根布局
* - 顶栏 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-bottom: 0;
/* 盖过 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%;
}
/* 悬浮卡片:居中模式尺寸与原先一致(520 宽、720/视口上限),无边框 + 主色高亮阴影 */
.login-auth-split--center .auth-right-wrap {
width: min(520px, calc(100vw - 2rem)) !important;
max-width: min(520px, calc(100vw - 2rem));
height: auto;
max-height: calc(100dvh - 6.5rem);
padding: 1.75rem 2rem 2rem;
overflow: hidden auto;
background-color: var(--el-bg-color);
border: none;
border-radius: 16px;
box-shadow:
0 6px 20px rgb(15 23 42 / 9%),
0 14px 36px rgb(15 23 42 / 10%),
0 0 18px color-mix(in srgb, var(--el-color-primary) 16%, transparent),
0 0 32px color-mix(in srgb, var(--el-color-primary) 7%, transparent);
}
.login-auth-split--center .auth-right-wrap .form {
height: auto;
min-height: 0;
padding-top: 1rem;
padding-bottom: 1rem;
}
html.dark .login-auth-split--center .auth-right-wrap {
border: none;
box-shadow:
0 8px 28px rgb(0 0 0 / 42%),
0 16px 44px rgb(0 0 0 / 46%),
0 0 22px color-mix(in srgb, var(--el-color-primary) 20%, transparent),
0 0 36px color-mix(in srgb, var(--el-color-primary) 9%, 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%);
}
@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(520px, calc(100vw - 1.5rem)) !important;
max-width: min(520px, calc(100vw - 1.5rem));
max-height: calc(100dvh - 6rem);
}
}
/* 授权页表单区域(左右分栏时) */
.auth-right-wrap {
@apply relative w-[440px] shrink-0 h-[720px] py-[5px] overflow-hidden
max-sm:px-7 max-sm:w-full max-sm:h-auto max-sm:max-h-[calc(100vh-10rem)]
animate-[slideInRight_0.6s_cubic-bezier(0.25,0.46,0.45,0.94)_forwards]
max-md:animate-none;
.form {
@apply h-full py-[40px];
}
.title {
@apply text-g-900 text-4xl font-semibold max-md:text-3xl max-sm:pt-10;
}
.sub-title {
@apply mt-[10px] text-g-600 text-sm;
}
.custom-height {
@apply !h-[40px];
}
}
@keyframes slideInRight {
from {
opacity: 0;
transform: translateX(30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@@ -1,92 +0,0 @@
@use "@styles/core/mixin.scss" as *;
// 设置抽屉模态框样式
.setting-modal {
background: transparent !important;
.el-drawer {
// 背景滤镜效果
background: rgba($color: #fff, $alpha: 50%) !important;
box-shadow: 0 0 30px rgb(0 0 0 / 10%) !important;
@include backdropBlur();
.setting-box-wrap {
display: flex;
flex-wrap: wrap;
align-items: center;
width: calc(100% + 15px);
margin-bottom: 10px;
.setting-item {
box-sizing: border-box;
width: calc(33.333% - 15px);
margin-right: 15px;
text-align: center;
.box {
position: relative;
box-sizing: border-box;
display: flex;
height: 52px;
overflow: hidden;
cursor: pointer;
border: 2px solid var(--default-border);
border-radius: 8px;
box-shadow: 0 0 8px 0 rgb(0 0 0 / 10%);
transition: box-shadow 0.1s;
&.mt-16 {
margin-top: 16px;
}
&.is-active {
border: 2px solid var(--theme-color);
}
img {
width: 100%;
height: 100%;
}
}
.name {
margin-top: 6px;
font-size: 14px;
text-align: center;
}
}
}
}
// 去除滚动条
.el-drawer__body::-webkit-scrollbar {
width: 0 !important;
}
}
.dark {
.setting-modal {
.el-drawer {
background: rgba($color: #000, $alpha: 50%) !important;
.setting-item {
.box {
border: 2px solid transparent;
}
}
}
}
}
// 去除火狐浏览器滚动条
:deep(.el-drawer__body) {
scrollbar-width: none;
}
// 移动端隐藏
@media screen and (width <= 800px) {
.mobile-hide {
display: none !important;
}
}
@@ -1,258 +0,0 @@
@use "@styles/core/mixin.scss" as *;
// 菜单样式变量
$menu-height: 42px;
$menu-icon-size: 20px;
$menu-font-size: 14px;
$hover-bg-color: var(--fa-gray-200);
$popup-menu-height: 40px;
$popup-menu-padding: 8px;
$popup-menu-margin: 5px;
$popup-menu-radius: 6px;
// 通用菜单项样式
@mixin menu-item-base {
width: calc(100% - 16px);
margin-left: 8px;
border-radius: 6px;
.menu-icon {
margin-left: -7px;
}
}
// 通用 hover 样式
@mixin menu-hover($bg-color) {
.el-sub-menu__title:hover,
.el-menu-item:not(.is-active):hover {
background: $bg-color !important;
}
}
// 通用选中样式
@mixin menu-active($color, $bg-color, $icon-color: var(--theme-color)) {
.el-menu-item.is-active {
color: $color !important;
background-color: $bg-color;
.menu-icon {
.art-svg-icon {
color: $icon-color !important;
}
}
}
}
// 弹窗菜单项样式
@mixin popup-menu-item {
height: $popup-menu-height;
margin-bottom: $popup-menu-margin;
border-radius: $popup-menu-radius;
.menu-icon {
margin-right: 5px;
}
&:last-of-type {
margin-bottom: 0;
}
}
// 主题菜单通用样式(合并 design 和 dark 主题的共同逻辑)
@mixin theme-menu-base {
.el-sub-menu__title,
.el-menu-item {
@include menu-item-base;
}
}
// 弹窗菜单通用样式
@mixin popup-menu-base($hover-bg, $active-color, $active-bg) {
.el-menu--popup {
padding: $popup-menu-padding;
.el-sub-menu__title:hover,
.el-menu-item:hover {
background-color: $hover-bg !important;
border-radius: $popup-menu-radius;
}
.el-menu-item {
@include popup-menu-item;
&.is-active {
color: $active-color !important;
background-color: $active-bg !important;
}
}
.el-sub-menu {
@include popup-menu-item;
height: $popup-menu-height !important;
.el-sub-menu__title {
height: $popup-menu-height !important;
border-radius: $popup-menu-radius;
}
}
}
}
.layout-sidebar {
// ---------------------- Modify default style ----------------------
// 菜单折叠样式
.menu-left-close {
.header {
.logo {
margin: 0 auto;
}
}
}
// 菜单图标
.menu-icon {
margin-right: 8px;
font-size: $menu-icon-size;
}
// 菜单高度
.el-sub-menu__title,
.el-menu-item {
height: $menu-height !important;
margin-bottom: 4px;
line-height: $menu-height !important;
span {
font-size: $menu-font-size !important;
@include ellipsis();
}
}
// 右侧箭头
.el-sub-menu__icon-arrow {
width: 13px !important;
font-size: 13px !important;
}
// 菜单折叠
.el-menu--collapse {
.el-sub-menu.is-active {
.el-sub-menu__title {
.menu-icon {
.art-svg-icon {
// 选中菜单图标颜色
color: var(--theme-color) !important;
}
}
}
}
}
// ---------------------- Design theme menu ----------------------
.el-menu-design {
@include theme-menu-base;
@include menu-active(var(--theme-color), var(--el-color-primary-light-9));
@include menu-hover($hover-bg-color);
.el-sub-menu__icon-arrow {
color: var(--fa-gray-600);
}
}
// ---------------------- Dark theme menu ----------------------
.el-menu-dark {
@include theme-menu-base;
@include menu-active(#fff, #27282d, #fff);
@include menu-hover(#0f1015);
.el-sub-menu__icon-arrow {
color: var(--fa-gray-400);
}
}
// ---------------------- Light theme menu ----------------------
.el-menu-light {
.el-sub-menu__title,
.el-menu-item {
.menu-icon {
margin-left: 1px;
}
}
.el-menu-item.is-active {
background-color: var(--el-color-primary-light-9);
.art-svg-icon {
color: var(--theme-color) !important;
}
&::before {
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
content: "";
background: var(--theme-color);
}
}
@include menu-hover($hover-bg-color);
.el-sub-menu__icon-arrow {
color: var(--fa-gray-600);
}
}
}
@media only screen and (width <= 640px) {
.layout-sidebar {
.el-menu-design {
> .el-sub-menu {
margin-left: 0;
}
.el-sub-menu {
width: 100% !important;
}
}
}
}
// 菜单折叠 hover 弹窗样式(浅色主题)
.el-menu--vertical,
.el-menu--popup-container {
@include popup-menu-base(var(--fa-gray-200), var(--fa-gray-900), var(--fa-gray-200));
}
// 暗黑模式菜单样式
.dark {
.el-menu--vertical,
.el-menu--popup-container {
@include popup-menu-base(var(--fa-gray-200), var(--fa-gray-900), #292a2e);
}
.layout-sidebar {
// 图标颜色、文字颜色
.menu-icon .art-svg-icon,
.menu-name {
color: var(--fa-gray-800) !important;
}
// 选中的文字颜色跟图标颜色
.el-menu-item.is-active {
span,
.menu-icon .art-svg-icon {
color: var(--theme-color) !important;
}
}
// 右侧箭头颜色
.el-sub-menu__icon-arrow {
color: #fff;
}
}
}
@@ -1,251 +0,0 @@
.layout-sidebar {
display: flex;
height: 100vh;
user-select: none;
scrollbar-width: none;
border-right: 1px solid var(--fa-card-border);
&.no-border {
border-right: none !important;
}
// 自定义滚动条宽度
:deep(.el-scrollbar__bar.is-vertical) {
width: 4px;
}
:deep(.el-scrollbar__thumb) {
right: -2px;
background-color: #ccc;
border-radius: 2px;
}
.dual-menu-left {
position: relative;
width: 80px;
height: 100%;
border-right: 1px solid var(--fa-card-border) !important;
transition: width 0.25s;
.logo {
margin: auto;
margin-top: 12px;
margin-bottom: 3px;
cursor: pointer;
}
ul {
li {
> div {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 8px;
overflow: hidden;
text-align: center;
cursor: pointer;
border-radius: 5px;
.art-svg-icon {
display: block;
margin: 0 auto;
font-size: 20px;
}
span {
display: -webkit-box;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 1;
line-clamp: 1;
font-size: 12px;
-webkit-box-orient: vertical;
}
&.is-active {
background: var(--el-color-primary-light-9);
.art-svg-icon,
span {
color: var(--theme-color) !important;
}
}
}
}
}
.switch-btn {
position: absolute;
right: 0;
bottom: 15px;
left: 0;
margin: auto;
}
}
.menu-left {
position: relative;
box-sizing: border-box;
height: 100vh;
@media only screen and (width <= 640px) {
height: 100dvh;
}
.el-menu {
height: 100%;
}
&:hover {
.dual-menu-collapse-btn {
opacity: 1 !important;
}
}
.dual-menu-collapse-btn {
position: absolute;
top: 50%;
right: -11px;
z-index: 10;
width: 11px;
height: 50px;
cursor: pointer;
background-color: var(--default-box-color);
border: 1px solid var(--fa-card-border);
border-radius: 0 15px 15px 0;
opacity: 0;
transform: translateY(-50%);
transition: opacity 0.2s;
&:hover {
.art-svg-icon {
color: var(--fa-gray-800) !important;
}
}
.art-svg-icon {
position: absolute;
top: 0;
bottom: 0;
left: -4px;
margin: auto;
transition: all 0.3s;
}
}
}
.header {
position: relative;
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
height: 60px;
overflow: hidden;
line-height: 60px;
cursor: pointer;
.logo {
margin-left: 22px;
}
p {
position: absolute;
top: 0;
bottom: 0;
left: 58px;
box-sizing: border-box;
margin-left: 10px;
font-size: 18px;
&.is-dual-menu-name {
left: 25px;
margin: auto;
}
}
}
.el-menu {
box-sizing: border-box;
// 防止菜单内的滚动影响整个页面滚动
overscroll-behavior: contain;
scrollbar-width: none;
border-right: 0;
-ms-scroll-chaining: contain;
&::-webkit-scrollbar {
width: 0 !important;
}
}
.menu-model {
display: none;
}
}
@media only screen and (width <= 800px) {
.layout-sidebar {
width: 0;
.header {
height: 50px;
line-height: 50px;
}
.el-menu {
height: calc(100vh - 60px);
}
.el-menu--collapse {
width: 0;
}
// 折叠状态下的header样式
.menu-left-close .header {
.logo {
display: none;
}
p {
left: 16px;
font-size: 0;
opacity: 0 !important;
}
}
.menu-model {
position: fixed;
top: 0;
left: 0;
z-index: -1;
display: block;
width: 100%;
height: 100vh;
background: rgba($color: #000, $alpha: 50%);
transition: opacity 0.2s ease-in-out;
}
}
}
@media only screen and (width <= 640px) {
.layout-sidebar {
border-right: 0 !important;
}
}
.dark {
.layout-sidebar {
border-right: 1px solid rgb(255 255 255 / 13%);
:deep(.el-scrollbar__thumb) {
background-color: #777;
}
.dual-menu-left {
border-right: 1px solid rgb(255 255 255 / 9%) !important;
}
}
}
-124
View File
@@ -1,124 +0,0 @@
.fa-table {
position: relative;
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
.fa-table__main {
flex: 1;
min-height: 0;
padding-top: 10px;
// VueDraggable 透传高度,确保 ElTable height: 100% 能正确解析
> * {
height: 100%;
}
}
.el-table {
height: 100%;
}
:deep(.el-loading-mask) {
z-index: 100;
background-color: var(--default-box-color) !important;
}
// Loading 过渡动画 - 消失时淡出
.loading-fade-leave-active {
transition: opacity 0.3s ease-out;
}
.loading-fade-leave-to {
opacity: 0;
}
// 空状态垂直居中
&.is-empty {
:deep(.el-table__body-wrapper) {
display: flex;
align-items: center;
justify-content: center;
}
}
.pagination {
display: flex;
flex-shrink: 0;
padding-top: 13px;
:deep(.el-select) {
width: 102px !important;
}
// 分页对齐方式
&.left {
justify-content: flex-start;
}
&.center {
justify-content: center;
}
&.right {
justify-content: flex-end;
}
// 自定义分页组件样式
&.custom-pagination {
:deep(.el-pagination) {
.btn-prev,
.btn-next {
background-color: transparent;
border: 1px solid var(--fa-gray-300);
transition: border-color 0.15s;
&:hover:not(.is-disabled) {
color: var(--theme-color);
border-color: var(--theme-color);
}
}
li {
box-sizing: border-box;
font-weight: 400 !important;
background-color: transparent;
border: 1px solid var(--fa-gray-300);
transition: border-color 0.15s;
&.is-active {
font-weight: 400;
color: #fff;
background-color: var(--theme-color);
border: 1px solid var(--theme-color);
}
&:hover:not(.is-disabled) {
border-color: var(--theme-color);
}
}
}
}
}
}
// 表格按钮悬浮效果
.hover-btn {
&:hover {
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
filter: brightness(1.1);
transform: translateY(-2px) scale(1.05);
}
}
// 移动端分页
@media (width <= 640px) {
:deep(.el-pagination) {
display: flex;
flex-wrap: wrap;
gap: 15px 0;
align-items: center;
justify-content: center;
}
}
-273
View File
@@ -1,273 +0,0 @@
$box-radius: calc(var(--custom-radius) / 3 + 2px);
// 全屏容器 z-index 调整
.w-e-full-screen-container {
z-index: 100 !important;
}
/* 编辑器容器 */
.editor-wrapper {
width: 100%;
height: 100%;
border: 1px solid var(--fa-gray-300);
border-radius: $box-radius !important;
.w-e-bar {
border-radius: $box-radius $box-radius 0 0 !important;
}
.menu-item {
display: flex;
flex-direction: row;
align-items: center;
i {
margin-right: 5px;
}
}
/* 工具栏 */
.editor-toolbar {
border-bottom: 1px solid var(--default-border);
}
/* 下拉选择框配置 */
.w-e-select-list {
min-width: 140px;
padding: 5px 10px 10px;
border: none;
border-radius: $box-radius;
}
/* 下拉选择框元素配置 */
.w-e-select-list ul li {
margin-top: 5px;
font-size: 15px !important;
border-radius: $box-radius;
}
/* 下拉选择框 正文文字大小调整 */
.w-e-select-list ul li:last-of-type {
font-size: 16px !important;
}
/* 下拉选择框 hover 样式调整 */
.w-e-select-list ul li:hover {
background-color: var(--fa-gray-200);
}
:root {
/* 激活颜色 */
--w-e-toolbar-active-bg-color: var(--fa-gray-200);
/* toolbar 图标和文字颜色 */
--w-e-toolbar-color: #000;
/* 表格选中时候的边框颜色 */
--w-e-textarea-selected-border-color: #ddd;
/* 表格头背景颜色 */
--w-e-textarea-slight-bg-color: var(--fa-gray-200);
}
/* 工具栏按钮样式 */
.w-e-bar-item svg {
fill: var(--fa-gray-800);
}
.w-e-bar-item button {
color: var(--fa-gray-800);
border-radius: $box-radius;
}
/* 工具栏 hover 按钮背景颜色 */
.w-e-bar-item button:hover {
background-color: var(--fa-gray-200);
}
/* 工具栏分割线 */
.w-e-bar-divider {
height: 20px;
margin-top: 10px;
background-color: #ccc;
}
/* 工具栏菜单 */
.w-e-bar-item-group .w-e-bar-item-menus-container {
min-width: 120px;
padding: 10px 0;
border: none;
border-radius: $box-radius;
.w-e-bar-item {
button {
width: 100%;
margin: 0 5px;
}
}
}
/* 代码块 */
.w-e-text-container [data-slate-editor] pre > code {
padding: 0.6rem 1rem;
background-color: var(--fa-gray-50);
border-radius: $box-radius;
}
/* 弹出框 */
.w-e-drop-panel {
border: 0;
border-radius: $box-radius;
}
a {
color: #318ef4;
}
.w-e-text-container {
[data-slate-editor] {
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0.8em 0 0.4em;
font-weight: 700;
line-height: 1.35;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.25em;
}
h4 {
font-size: 1.125em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 0.875em;
}
ul,
ol {
padding-left: 1.5em;
margin: 0.8em 0;
}
ul {
list-style: disc;
}
ol {
list-style: decimal;
}
li {
margin: 0.25em 0;
}
ul ul {
list-style: circle;
}
ul ul ul {
list-style: square;
}
}
strong,
b {
font-weight: 700;
}
i,
em {
font-style: italic;
}
}
/* 表格样式优化 */
.w-e-text-container [data-slate-editor] .table-container th {
border-right: none;
}
.w-e-text-container [data-slate-editor] .table-container th:last-of-type {
border-right: 1px solid #ccc !important;
}
/* 引用 */
.w-e-text-container [data-slate-editor] blockquote {
background-color: var(--fa-gray-200);
border-left: 4px solid var(--fa-gray-300);
}
/* 输入区域弹出 bar */
.w-e-hover-bar {
border-radius: $box-radius;
}
/* 超链接弹窗 */
.w-e-modal {
border: none;
border-radius: $box-radius;
}
/* 图片样式调整 */
.w-e-text-container [data-slate-editor] .w-e-selected-image-container {
overflow: inherit;
&:hover {
border: 0;
}
img {
border: 1px solid transparent;
transition: border 0.3s;
&:hover {
border: 1px solid #318ef4 !important;
}
}
.w-e-image-dragger {
width: 12px;
height: 12px;
background-color: #318ef4;
border: 2px solid #fff;
border-radius: $box-radius;
}
.left-top {
top: -6px;
left: -6px;
}
.right-top {
top: -6px;
right: -6px;
}
.left-bottom {
bottom: -6px;
left: -6px;
}
.right-bottom {
right: -6px;
bottom: -6px;
}
}
}
+3 -21
View File
@@ -7,6 +7,9 @@
// Element Plus 样式优化
@use "./core/el-ui";
// Element Plus 功能性颜色覆写 CSS 变量
@use "./core/variables";
// Element Plus 暗黑主题
@use "./core/el-dark";
@@ -21,24 +24,3 @@
// 主题切换圆形扩散动画
@use "./core/theme-animation";
// CRUD 页面通用样式
@use "./core/crud";
// 布局组件样式
@use "./layouts";
// 侧边栏菜单样式
@use "./fa-sidebar-menu";
// 侧边栏菜单主题样式
@use "./fa-sidebar-menu-theme";
// 设置面板样式
@use "./fa-settings-panel";
// 表格组件样式
@use "./fa-table";
// 富文本编辑器样式
@use "./fa-wang-editor";
-8
View File
@@ -1,8 +0,0 @@
/**
* 全局 SCSS 变量(由 vite.config.ts → css.preprocessorOptions.scss.additionalData 注入到每个 `.vue` 的 `lang="scss"`)
*
* 默认主色请与 `src/config/setting.ts` 中 `themeColorPresets` 首项、主题切换逻辑保持一致。
*/
// 供组件内 `$primary-base` 等引用(可选)
$primary-base: #4080ff !default;