feat: 迁移前端资源文件并重构项目结构

refactor: 优化前端代码结构和资源管理

style: 调整前端代码格式和样式

chore: 更新.gitignore和构建配置

fix: 修复前端资源路径和引用问题

docs: 更新前端文档和注释

perf: 优化前端性能和加载速度

test: 更新前端测试用例

build: 调整前端构建配置

ci: 更新CI/CD配置
This commit is contained in:
zhangtao
2026-05-09 00:46:43 +08:00
parent 1bd125d99b
commit bf81480ada
967 changed files with 21018 additions and 83019 deletions
+299
View File
@@ -0,0 +1,299 @@
// 全局样式
// 顶部进度条颜色
#nprogress .bar {
z-index: 2400;
background-color: color-mix(in srgb, var(--theme-color) 70%, white);
}
#nprogress .peg {
box-shadow:
0 0 10px var(--theme-color),
0 0 5px var(--theme-color) !important;
}
#nprogress .spinner-icon {
border-top-color: var(--theme-color) !important;
border-left-color: var(--theme-color) !important;
}
// 处理移动端组件兼容性
@media screen and (max-width: 640px) {
* {
cursor: default !important;
}
}
// 背景滤镜
*,
::before,
::after {
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
// 色弱模式
.color-weak {
filter: invert(80%);
-webkit-filter: invert(80%);
}
#noop {
display: none;
}
// 语言切换选中样式
.langDropDownStyle {
// 选中项背景颜色
.is-selected {
background-color: var(--art-el-active-color) !important;
}
// 语言切换按钮菜单样式优化
.lang-btn-item {
.el-dropdown-menu__item {
padding-left: 13px !important;
padding-right: 6px !important;
margin-bottom: 3px !important;
}
&:last-child {
.el-dropdown-menu__item {
margin-bottom: 0 !important;
}
}
.menu-txt {
min-width: 60px;
display: block;
}
i {
font-size: 10px;
margin-left: 10px;
}
}
}
// 盒子默认边框
.page-content {
border: 1px solid var(--art-card-border) !important;
}
@mixin art-card-base($border-color, $shadow: none, $radius-diff: 4px) {
background: var(--default-box-color);
border: 1px solid #{$border-color} !important;
border-radius: calc(var(--custom-radius) + #{$radius-diff}) !important;
box-shadow: #{$shadow} !important;
--el-card-border-color: var(--default-border) !important;
}
.art-card,
.art-card-sm,
.art-card-xs {
border: 1px solid var(--art-card-border);
}
// 盒子边框
[data-box-mode='border-mode'] {
.page-content,
.art-table-card {
border: 1px solid var(--art-card-border) !important;
}
.art-card {
@include art-card-base(var(--art-card-border), none, 4px);
}
.art-card-sm {
@include art-card-base(var(--art-card-border), none, 0px);
}
.art-card-xs {
@include art-card-base(var(--art-card-border), none, -4px);
}
}
// 盒子阴影
[data-box-mode='shadow-mode'] {
.page-content,
.art-table-card {
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.04) !important;
border: 1px solid var(--art-gray-200) !important;
}
.layout-sidebar {
border-right: 1px solid var(--art-card-border) !important;
}
.art-card {
@include art-card-base(
var(--art-gray-200),
(0 1px 3px 0 rgba(0, 0, 0, 0.03), 0 1px 2px -1px rgba(0, 0, 0, 0.08)),
4px
);
}
.art-card-sm {
@include art-card-base(
var(--art-gray-200),
(0 1px 3px 0 rgba(0, 0, 0, 0.03), 0 1px 2px -1px rgba(0, 0, 0, 0.08)),
2px
);
}
.art-card-xs {
@include art-card-base(
var(--art-gray-200),
(0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 1px -1px rgba(0, 0, 0, 0.08)),
-4px
);
}
}
// 元素全屏
.el-full-screen {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100vw !important;
height: 100% !important;
z-index: 2300;
margin-top: 0;
padding: 15px;
box-sizing: border-box;
background-color: var(--default-box-color);
display: flex;
flex-direction: column;
}
// 表格卡片
.art-table-card {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
margin-top: 12px;
border-radius: calc(var(--custom-radius) / 2 + 2px) !important;
.el-card__body {
height: 100%;
overflow: hidden;
}
}
// 容器全高:沿布局 flex 链填满 `#app-scroll-main` 内剩余高度,底部自然对齐 #app-content 的 padding(勿再用 100vh 估算)
.art-full-height {
box-sizing: border-box;
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
min-width: 0;
width: 100%;
@media (max-width: 640px) {
flex: 0 1 auto;
min-height: 0;
height: auto;
}
}
// 徽章样式
.art-badge {
position: absolute;
top: 0;
right: 20px;
bottom: 0;
width: 6px;
height: 6px;
margin: auto;
background: #ff3860;
border-radius: 50%;
animation: breathe 1.5s ease-in-out infinite;
&.art-badge-horizontal {
right: 0;
}
&.art-badge-mixed {
right: 0;
}
&.art-badge-dual {
right: 5px;
top: 5px;
bottom: auto;
}
}
// 文字徽章样式
.art-text-badge {
position: absolute;
top: 0;
right: 12px;
bottom: 0;
min-width: 20px;
height: 18px;
line-height: 17px;
padding: 0 5px;
margin: auto;
font-size: 10px;
color: #fff;
text-align: center;
background: #fd4e4e;
border-radius: 4px;
}
@keyframes breathe {
0% {
opacity: 0.7;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.1);
}
100% {
opacity: 0.7;
transform: scale(1);
}
}
// 修复老机型 loading 定位问题
.art-loading-fix {
position: fixed !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
width: 100vw !important;
height: 100vh !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.art-loading-fix .el-loading-spinner {
position: static !important;
top: auto !important;
left: auto !important;
transform: none !important;
}
// 去除移动端点击背景色
@media screen and (max-width: 1180px) {
* {
-webkit-tap-highlight-color: transparent;
}
}
+93
View File
@@ -0,0 +1,93 @@
/*
* 深色主题
* 单页面移除深色主题 document.getElementsByTagName("html")[0].removeAttribute('class')
*/
$font-color: rgba(#ffffff, 0.85);
/* 覆盖element-plus默认深色背景色 */
html.dark {
// element-plus
--el-bg-color: var(--default-box-color);
--el-text-color-regular: #{$font-color};
// 富文本编辑器
// 工具栏背景颜色
--w-e-toolbar-bg-color: #18191c;
// 输入区域背景颜色
--w-e-textarea-bg-color: #090909;
// 工具栏文字颜色
--w-e-toolbar-color: var(--art-gray-600);
// 选中菜单颜色
--w-e-toolbar-active-bg-color: #25262b;
// 弹窗边框颜色
--w-e-toolbar-border-color: var(--default-border-dashed);
// 分割线颜色
--w-e-textarea-border-color: var(--default-border-dashed);
// 链接输入框边框颜色
--w-e-modal-button-border-color: var(--default-border-dashed);
// 表格头颜色
--w-e-textarea-slight-bg-color: #090909;
// 按钮背景颜色
--w-e-modal-button-bg-color: #090909;
// hover toolbar 背景颜色
--w-e-toolbar-active-color: var(--art-gray-800);
}
.dark {
.page-content .article-list .item .left .outer > div {
border-right-color: var(--dark-border-color) !important;
}
// 富文本编辑器
.editor-wrapper {
*:not(pre code *) {
color: inherit !important;
}
}
// 分隔线
.w-e-bar-divider {
background-color: var(--art-gray-300) !important;
}
.w-e-select-list,
.w-e-drop-panel,
.w-e-bar-item-group .w-e-bar-item-menus-container,
.w-e-text-container [data-slate-editor] pre > code {
border: 1px solid var(--default-border) !important;
}
// 下拉选择框
.w-e-select-list {
background-color: var(--default-box-color) !important;
}
/* 下拉选择框 hover 样式调整 */
.w-e-select-list ul li:hover,
/* 工具栏 hover 按钮背景颜色 */
.w-e-bar-item button:hover {
background-color: #090909 !important;
}
/* 代码块 */
.w-e-text-container [data-slate-editor] pre > code {
background-color: #25262b !important;
text-shadow: none !important;
}
/* 引用 */
.w-e-text-container [data-slate-editor] blockquote {
border-left: 4px solid var(--default-border-dashed) !important;
background-color: var(--art-color);
}
.editor-wrapper {
.w-e-text-container [data-slate-editor] .table-container th:last-of-type {
border-right: 1px solid var(--default-border-dashed) !important;
}
.w-e-modal {
background-color: var(--art-color);
}
}
}
@@ -0,0 +1,2 @@
// 导入暗黑主题
@use 'element-plus/theme-chalk/src/dark/css-vars.scss' as *;
@@ -0,0 +1,34 @@
// 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,
'success': (
'base': #13deb9
),
'warning': (
'base': #ffae1f
),
'danger': (
'base': #ff4d4f
),
'error': (
'base': #fa896b
)
),
$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'
)
);
+519
View File
@@ -0,0 +1,519 @@
// 优化 Element Plus 组件库默认样式
:root {
// 系统主色
--main-color: var(--el-color-primary);
--el-color-white: white !important;
--el-color-black: white !important;
// 输入框边框颜色
// --el-border-color: #E4E4E7 !important; // DCDFE6
// 按钮粗度
--el-font-weight-primary: 400 !important;
--el-component-custom-height: 36px !important;
--el-component-size: var(--el-component-custom-height) !important;
// 边框、按钮圆角...
--el-border-radius-base: calc(var(--custom-radius) / 3 + 2px) !important;
--el-border-radius-small: calc(var(--custom-radius) / 3 + 4px) !important;
--el-messagebox-border-radius: calc(var(--custom-radius) / 3 + 4px) !important;
--el-popover-border-radius: calc(var(--custom-radius) / 3 + 4px) !important;
.region .el-radio-button__original-radio:checked + .el-radio-button__inner {
color: var(--theme-color);
}
}
// 优化 el-form-item 标签高度
.el-form-item__label {
height: var(--el-component-custom-height) !important;
line-height: var(--el-component-custom-height) !important;
}
// 日期选择器
.el-date-range-picker {
--el-datepicker-inrange-bg-color: var(--art-gray-200) !important;
}
// el-card 背景色跟系统背景色保持一致
html.dark .el-card {
--el-card-bg-color: var(--default-box-color) !important;
}
// 修改 el-pagination 大小
.el-pagination--default {
& {
--el-pagination-button-width: 32px !important;
--el-pagination-button-height: var(--el-pagination-button-width) !important;
}
@media (max-width: 1180px) {
& {
--el-pagination-button-width: 28px !important;
}
}
.el-select--default .el-select__wrapper {
min-height: var(--el-pagination-button-width) !important;
}
.el-pagination__jump .el-input {
height: var(--el-pagination-button-width) !important;
}
}
.el-pager li {
padding: 0 10px !important;
// border: 1px solid red !important;
}
// 优化菜单折叠展开动画(提升动画流畅度)
.el-menu.el-menu--inline {
transition: max-height 0.26s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
// 优化菜单 item hover 动画(提升鼠标跟手感)
.el-sub-menu__title,
.el-menu-item {
transition: background-color 0s !important;
}
// -------------------------------- 修改 el-size=default 组件默认高度 start --------------------------------
// 修改 el-button 高度
.el-button--default {
height: var(--el-component-custom-height) !important;
}
// circle 按钮宽度优化
.el-button--default.is-circle {
width: var(--el-component-custom-height) !important;
}
// 修改 el-select 高度
.el-select--default {
.el-select__wrapper {
min-height: var(--el-component-custom-height) !important;
}
}
// 修改 el-checkbox-button 高度
.el-checkbox-button--default .el-checkbox-button__inner,
// 修改 el-radio-button 高度
.el-radio-button--default .el-radio-button__inner {
padding: 10px 15px !important;
}
// -------------------------------- 修改 el-size=default 组件默认高度 end --------------------------------
.el-pagination.is-background .btn-next,
.el-pagination.is-background .btn-prev,
.el-pagination.is-background .el-pager li {
border-radius: 6px;
}
.el-popover {
min-width: 80px;
border-radius: var(--el-border-radius-small) !important;
}
.el-dialog {
border-radius: 100px !important;
border-radius: calc(var(--custom-radius) / 1.2 + 2px) !important;
overflow: hidden;
}
.el-dialog__header {
.el-dialog__title {
font-size: 16px;
}
}
.el-dialog__body {
padding: 25px 0 !important;
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;
}
.el-dialog.el-dialog-border {
.el-dialog__body {
// 上边框
&::before,
// 下边框
&::after {
content: '';
position: absolute;
left: -16px;
width: calc(100% + 32px);
height: 1px;
background-color: var(--art-gray-300);
}
&::before {
top: 0;
}
&::after {
bottom: 0;
}
}
}
// el-message 样式优化
.el-message {
background-color: var(--default-box-color) !important;
border: 0 !important;
box-shadow:
0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 3px 6px -4px rgba(0, 0, 0, 0.12),
0 9px 28px 8px rgba(0, 0, 0, 0.05) !important;
p {
font-size: 13px;
}
}
// 修改 el-dropdown 样式
.el-dropdown-menu {
padding: 6px !important;
border-radius: 10px !important;
border: none !important;
.el-dropdown-menu__item {
padding: 6px 16px !important;
border-radius: 6px !important;
&:hover:not(.is-disabled) {
color: var(--art-gray-900) !important;
background-color: var(--art-el-active-color) !important;
}
&:focus:not(.is-disabled) {
color: var(--art-gray-900) !important;
background-color: var(--art-gray-200) !important;
}
}
}
// 隐藏 select、dropdown 的三角
.el-select__popper,
.el-dropdown__popper {
margin-top: -6px !important;
.el-popper__arrow {
display: none;
}
}
.el-dropdown-selfdefine:focus {
outline: none !important;
}
// 处理移动端组件兼容性
@media screen and (max-width: 640px) {
.el-message-box,
.el-dialog {
width: calc(100% - 24px) !important;
}
.el-date-picker.has-sidebar.has-time {
width: calc(100% - 24px);
left: 12px !important;
}
.el-picker-panel *[slot='sidebar'],
.el-picker-panel__sidebar {
display: none;
}
.el-picker-panel *[slot='sidebar'] + .el-picker-panel__body,
.el-picker-panel__sidebar + .el-picker-panel__body {
margin-left: 0;
}
}
// 修改el-button样式
.el-button {
&.el-button--text {
background-color: transparent !important;
padding: 0 !important;
span {
margin-left: 0 !important;
}
}
}
// 修改el-tag样式
.el-tag {
font-weight: 500;
transition: all 0s !important;
&.el-tag--default {
height: 26px !important;
}
}
.el-checkbox-group {
&.el-table-filter__checkbox-group label.el-checkbox {
height: 17px !important;
.el-checkbox__label {
font-weight: 400 !important;
}
}
}
.el-radio--default {
// 优化单选按钮大小
.el-radio__input {
.el-radio__inner {
width: 16px;
height: 16px;
&::after {
width: 6px;
height: 6px;
}
}
}
}
.el-checkbox {
.el-checkbox__inner {
border-radius: 2px !important;
}
}
// 优化复选框样式
.el-checkbox--default {
.el-checkbox__inner {
width: 16px !important;
height: 16px !important;
border-radius: 4px !important;
&::before {
content: '';
height: 4px !important;
top: 5px !important;
background-color: #fff !important;
transform: scale(0.6) !important;
}
}
.is-checked {
.el-checkbox__inner {
&::after {
width: 3px;
height: 8px;
margin: auto;
border: 2px solid var(--el-checkbox-checked-icon-color);
border-left: 0;
border-top: 0;
transform: translate(-45%, -60%) rotate(45deg) scale(0.86) !important;
transform-origin: center;
}
}
}
}
.el-notification .el-notification__icon {
font-size: 22px !important;
}
// 修改 el-message-box 样式
.el-message-box__headerbtn .el-message-box__close,
.el-dialog__headerbtn .el-dialog__close {
top: 7px;
right: 7px;
width: 30px;
height: 30px;
border-radius: 5px;
transition: all 0.3s;
&:hover {
background-color: var(--art-hover-color) !important;
color: var(--art-gray-900) !important;
}
}
.el-message-box {
padding: 25px 20px !important;
}
.el-message-box__title {
font-weight: 500 !important;
}
.el-table__column-filter-trigger i {
color: var(--theme-color) !important;
margin: -3px 0 0 2px;
}
// 去除 el-dropdown 鼠标放上去出现的边框
.el-tooltip__trigger:focus-visible {
outline: unset;
}
// ipad 表单右侧按钮优化
@media screen and (max-width: 1180px) {
.el-table-fixed-column--right {
padding-right: 0 !important;
}
}
.login-out-dialog {
padding: 30px 20px !important;
border-radius: 10px !important;
}
// 修改 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);
// 修复 el-dialog 动画后宽度不自适应问题
.el-select__selected-item {
display: inline-block;
}
}
}
.dialog-fade-leave-active {
animation: fade-out 0.2s linear;
.el-dialog:not(.is-draggable) {
animation: dialog-close 0.5s;
}
}
@keyframes dialog-open {
0% {
opacity: 0;
transform: scale(0.2);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes dialog-close {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.2);
}
}
// 遮罩层动画
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
// 修改 el-select 样式
.el-select__popper:not(.el-tree-select__popper) {
.el-select-dropdown__list {
padding: 5px !important;
.el-select-dropdown__item {
height: 34px !important;
line-height: 34px !important;
border-radius: 6px !important;
&.is-selected {
color: var(--art-gray-900) !important;
font-weight: 400 !important;
background-color: var(--art-el-active-color) !important;
margin-bottom: 4px !important;
}
&:hover {
background-color: var(--art-hover-color) !important;
}
}
.el-select-dropdown__item:hover ~ .is-selected,
.el-select-dropdown__item.is-selected:has(~ .el-select-dropdown__item:hover) {
background-color: transparent !important;
}
}
}
// 修改 el-tree-select 样式
.el-tree-select__popper {
.el-select-dropdown__list {
padding: 5px !important;
.el-tree-node {
.el-tree-node__content {
height: 36px !important;
border-radius: 6px !important;
&:hover {
background-color: var(--art-gray-200) !important;
}
}
}
}
}
// 实现水波纹在文字下面效果
.el-button > span {
position: relative;
z-index: 10;
}
// 优化颜色选择器圆角
.el-color-picker__color {
border-radius: 2px !important;
}
// 优化日期时间选择器底部圆角
.el-picker-panel {
.el-picker-panel__footer {
border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base);
}
}
// 优化树型菜单样式
.el-tree-node__content {
border-radius: 4px;
margin-bottom: 4px;
padding: 1px 0;
&:hover {
background-color: var(--art-hover-color) !important;
}
}
.dark {
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: var(--art-gray-300) !important;
}
}
// 隐藏折叠菜单弹窗 hover 出现的边框
.menu-left-popper:focus-within,
.horizontal-menu-popper:focus-within {
box-shadow: none !important;
outline: none !important;
}
// 数字输入组件右侧按钮高度跟随自定义组件高度
.el-input-number--default.is-controls-right {
.el-input-number__decrease,
.el-input-number__increase {
height: calc((var(--el-component-size) / 2)) !important;
}
}
File diff suppressed because it is too large Load Diff
+157
View File
@@ -0,0 +1,157 @@
// sass 混合宏(函数)
/**
* 溢出省略号
* @param {Number} 行数
*/
@mixin ellipsis($rowCount: 1) {
@if $rowCount <=1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} @else {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $rowCount;
-webkit-box-orient: vertical;
}
}
/**
* 控制用户能否选中文本
* @param {String} 类型
*/
@mixin userSelect($value: none) {
user-select: $value;
-moz-user-select: $value;
-ms-user-select: $value;
-webkit-user-select: $value;
}
// 绝对定位居中
@mixin absoluteCenter() {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
/**
* css3动画
*
*/
@mixin animation(
$from: (
width: 0px
),
$to: (
width: 100px
),
$name: mymove,
$animate: mymove 2s 1 linear infinite
) {
-webkit-animation: $animate;
-o-animation: $animate;
animation: $animate;
@keyframes #{$name} {
from {
@each $key, $value in $from {
#{$key}: #{$value};
}
}
to {
@each $key, $value in $to {
#{$key}: #{$value};
}
}
}
@-webkit-keyframes #{$name} {
from {
@each $key, $value in $from {
$key: $value;
}
}
to {
@each $key, $value in $to {
$key: $value;
}
}
}
}
// 圆形盒子
@mixin circle($size: 11px, $bg: #fff) {
border-radius: 50%;
width: $size;
height: $size;
line-height: $size;
text-align: center;
background: $bg;
}
// placeholder
@mixin placeholder($color: #bbb) {
// Firefox
&::-moz-placeholder {
color: $color;
opacity: 1;
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $color;
}
&:placeholder-shown {
text-overflow: ellipsis;
}
}
//背景透明,文字不透明。兼容IE8
@mixin betterTransparentize($color, $alpha) {
$c: rgba($color, $alpha);
$ie_c: ie_hex_str($c);
background: rgba($color, 1);
background: $c;
background: transparent \9;
zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c});
-ms-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;
}
// 背景滤镜
@mixin backdropBlur() {
--tw-backdrop-blur: blur(30px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness)
var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate)
var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate)
var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast)
var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
+41
View File
@@ -0,0 +1,41 @@
@charset "UTF-8";
/*滚动条*/
/*滚动条整体部分,必须要设置*/
::-webkit-scrollbar {
width: 8px !important;
height: 0 !important;
}
/*滚动条的轨道*/
::-webkit-scrollbar-track {
background-color: var(--art-gray-200);
}
/*滚动条的滑块按钮*/
::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: #cccccc !important;
transition: all 0.2s;
-webkit-transition: all 0.2s;
}
::-webkit-scrollbar-thumb:hover {
background-color: #b0abab !important;
}
/*滚动条的上下两端的按钮*/
::-webkit-scrollbar-button {
height: 0px;
width: 0;
}
.dark {
::-webkit-scrollbar-track {
background-color: var(--default-bg-color);
}
::-webkit-scrollbar-thumb {
background-color: var(--art-gray-300) !important;
}
}
@@ -0,0 +1,104 @@
@use 'sass:map';
// === 变量区域 ===
$transition: (
// 动画持续时间
duration: 0.25s,
// 滑动动画的移动距离
distance: 15px,
// 默认缓动函数
easing: cubic-bezier(0.25, 0.1, 0.25, 1),
// 淡入淡出专用的缓动函数
fade-easing: cubic-bezier(0.4, 0, 0.6, 1)
);
// 抽取配置值函数,提高可复用性
@function transition-config($key) {
@return map.get($transition, $key);
}
// 变量简写
$duration: transition-config('duration');
$distance: transition-config('distance');
$easing: transition-config('easing');
$fade-easing: transition-config('fade-easing');
// === 动画类 ===
// 淡入淡出动画
.fade {
&-enter-active,
&-leave-active {
transition: opacity $duration $fade-easing;
will-change: opacity;
}
&-enter-from,
&-leave-to {
opacity: 0;
}
&-enter-to,
&-leave-from {
opacity: 1;
}
}
// 滑动动画通用样式
@mixin slide-transition($direction) {
$distance-x: 0;
$distance-y: 0;
@if $direction == 'left' {
$distance-x: -$distance;
} @else if $direction == 'right' {
$distance-x: $distance;
} @else if $direction == 'top' {
$distance-y: -$distance;
} @else if $direction == 'bottom' {
$distance-y: $distance;
}
&-enter-active {
transition:
opacity $duration $easing,
transform $duration $easing;
will-change: opacity, transform;
}
&-leave-active {
transition:
opacity calc($duration * 0.7) $easing,
transform calc($duration * 0.7) $easing;
will-change: opacity, transform;
}
&-enter-from {
opacity: 0;
transform: translate3d($distance-x, $distance-y, 0);
}
&-enter-to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
&-leave-to {
opacity: 0;
transform: translate3d(-$distance-x, -$distance-y, 0);
}
}
// 滑动动画方向类
.slide-left {
@include slide-transition('left');
}
.slide-right {
@include slide-transition('right');
}
.slide-top {
@include slide-transition('top');
}
.slide-bottom {
@include slide-transition('bottom');
}
+208
View File
@@ -0,0 +1,208 @@
@import 'tailwindcss';
@custom-variant dark (&:where(.dark, .dark *));
/* ==================== Light Mode Variables ==================== */
:root {
/* Base Colors */
--art-color: #ffffff;
--theme-color: var(--main-color);
/* Theme Colors - OKLCH Format */
--art-primary: oklch(0.7 0.23 260);
--art-secondary: oklch(0.72 0.19 231.6);
--art-error: oklch(0.73 0.15 25.3);
--art-info: oklch(0.58 0.03 254.1);
--art-success: oklch(0.78 0.17 166.1);
--art-warning: oklch(0.78 0.14 75.5);
--art-danger: oklch(0.68 0.22 25.3);
/* Gray Scale - Light Mode */
--art-gray-100: #f9fafb;
--art-gray-200: #f2f4f5;
--art-gray-300: #e6eaeb;
--art-gray-400: #dbdfe1;
--art-gray-500: #949eb7;
--art-gray-600: #7987a1;
--art-gray-700: #4d5875;
--art-gray-800: #383853;
--art-gray-900: #323251;
/* Border Colors */
--art-card-border: rgba(0, 0, 0, 0.08);
--default-border: #e2e8ee;
--default-border-dashed: #dbdfe9;
/* Background Colors */
--default-bg-color: #fafbfc;
--default-box-color: #ffffff;
/* Hover Color */
--art-hover-color: #edeff0;
/* Active Color */
--art-active-color: #f2f4f5;
/* Element Component Active Color */
--art-el-active-color: #f2f4f5;
}
/* ==================== Dark Mode Variables ==================== */
.dark {
/* Base Colors */
--art-color: #000000;
/* Gray Scale - Dark Mode */
--art-gray-100: #110f0f;
--art-gray-200: #17171c;
--art-gray-300: #393946;
--art-gray-400: #505062;
--art-gray-500: #73738c;
--art-gray-600: #8f8fa3;
--art-gray-700: #ababba;
--art-gray-800: #c7c7d1;
--art-gray-900: #e3e3e8;
/* Border Colors */
--art-card-border: rgba(255, 255, 255, 0.08);
--default-border: rgba(255, 255, 255, 0.1);
--default-border-dashed: #363843;
/* Background Colors */
--default-bg-color: #070707;
--default-box-color: #161618;
/* Hover Color */
--art-hover-color: #252530;
/* Active Color */
--art-active-color: #202226;
/* Element Component Active Color */
--art-el-active-color: #2e2e38;
}
/* ==================== Tailwind Theme Configuration ==================== */
@theme {
/* Box Color (Light: white / Dark: black) */
--color-box: var(--default-box-color);
/* System Theme Color */
--color-theme: var(--theme-color);
/* Hover Color */
--color-hover-color: var(--art-hover-color);
/* Active Color */
--color-active-color: var(--art-active-color);
/* Active Color */
--color-el-active-color: var(--art-active-color);
/* ElementPlus Theme Colors */
--color-primary: var(--art-primary);
--color-secondary: var(--art-secondary);
--color-error: var(--art-error);
--color-info: var(--art-info);
--color-success: var(--art-success);
--color-warning: var(--art-warning);
--color-danger: var(--art-danger);
/* Gray Scale Colors (Auto-adapts to dark mode) */
--color-g-100: var(--art-gray-100);
--color-g-200: var(--art-gray-200);
--color-g-300: var(--art-gray-300);
--color-g-400: var(--art-gray-400);
--color-g-500: var(--art-gray-500);
--color-g-600: var(--art-gray-600);
--color-g-700: var(--art-gray-700);
--color-g-800: var(--art-gray-800);
--color-g-900: var(--art-gray-900);
}
/* ==================== Custom Border Radius Utilities ==================== */
@utility rounded-custom-xs {
border-radius: calc(var(--custom-radius) / 2);
}
@utility rounded-custom-sm {
border-radius: calc(var(--custom-radius) / 2 + 2px);
}
/* ==================== Custom Utility Classes ==================== */
@layer utilities {
/* Flexbox Layout Utilities */
.flex-c {
@apply flex items-center;
}
.flex-b {
@apply flex justify-between;
}
.flex-cc {
@apply flex items-center justify-center;
}
.flex-cb {
@apply flex items-center justify-between;
}
/* Transition Utilities */
.tad-200 {
@apply transition-all duration-200;
}
.tad-300 {
@apply transition-all duration-300;
}
/* Border Utilities */
.border-full-d {
@apply border border-[var(--default-border)];
}
.border-b-d {
@apply border-b border-[var(--default-border)];
}
.border-t-d {
@apply border-t border-[var(--default-border)];
}
.border-l-d {
@apply border-l border-[var(--default-border)];
}
.border-r-d {
@apply border-r border-[var(--default-border)];
}
/* Cursor Utilities */
.c-p {
@apply cursor-pointer;
}
}
/* ==================== Custom Component Classes ==================== */
@layer components {
/* Art Card Header Component */
.art-card-header {
@apply flex justify-between pr-6 pb-1;
.title {
h4 {
@apply text-lg font-medium text-g-900;
}
p {
@apply mt-1 text-sm text-g-600;
span {
@apply ml-2 font-medium;
}
}
}
}
}
@@ -0,0 +1,63 @@
// 定义基础变量
$bg-animation-color-light: #000;
$bg-animation-color-dark: #fff;
$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;
}
&::view-transition-new(*) {
animation: clip $bg-animation-duration ease-in both;
}
&::view-transition-old(root) {
z-index: 1;
}
&::view-transition-new(root) {
z-index: 9999;
}
&.dark {
&::view-transition-old(*) {
animation: clip $bg-animation-duration ease-in reverse both;
}
&::view-transition-new(*) {
animation: none;
}
&::view-transition-old(root) {
z-index: 9999;
}
&::view-transition-new(root) {
z-index: 1;
}
}
}
// 定义动画
@keyframes clip {
from {
clip-path: circle(0% at var(--x) var(--y));
}
to {
clip-path: circle(var(--r) at var(--x) var(--y));
}
}
// body 相关样式
body {
background-color: var(--bg-animation-color);
}
+11
View File
@@ -0,0 +1,11 @@
// 主题切换过渡优化,优化除视觉上的不适感
.theme-change {
* {
transition: 0s !important;
}
.el-switch__core,
.el-switch__action {
transition: all 0.3s !important;
}
}
@@ -0,0 +1,98 @@
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #a6accd;
}
.hljs-string,
.hljs-section,
.hljs-selector-class,
.hljs-template-variable,
.hljs-deletion {
color: #aed07e !important;
}
.hljs-comment,
.hljs-quote {
color: #6f747d;
}
.hljs-doctag,
.hljs-keyword,
.hljs-formula {
color: #c792ea;
}
.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
color: #c86068;
}
.hljs-literal {
color: #56b6c2;
}
.hljs-string,
.hljs-regexp,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
color: #abb2bf;
}
.hljs-attribute {
color: #c792ea;
}
.hljs-function {
color: #c792ea;
}
.hljs-type {
color: #f07178;
}
.hljs-title {
color: #82aaff !important;
}
.hljs-built_in,
.hljs-class {
color: #82aaff;
}
// 括号
.hljs-params {
color: #a6accd;
}
.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
color: #de7e61;
}
.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id {
color: #61aeee;
}
.hljs-strong {
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
}
-329
View File
@@ -1,329 +0,0 @@
/* 暗黑模式通过 CSS 自定义变量,官方链接:https://element-plus.org/zh-CN/guide/dark-mode.html#%E9%80%9A%E8%BF%87-css */
/**
* Element Plus 主题最小回退变量(合并版)
*
* === 配色层级(同一主色:哪里深、哪里浅)===
* L0 页面画布:--el-bg-color / --el-bg-color-page(大面积)
* L1 内容区块:--el-bg-color-overlay(卡片/表格等)
* L2 卡片/表格容器面:--el-bg-color-overlay(抬升中性面)
* L3 表头/侧栏条:使用 fill 层级(不再做混色)
* L4 浮层(下拉/弹窗):面板底 = overlay,不用整板灌主色;强调在选项/按钮/focus
* L5 再嵌套浅填充:--el-fill-color-light(hover 槽、禁用底等)
* 标签栏 TagsView:使用 Element Plus fill/bg token
* 主色强度:点线控件(按钮、focus、选中字)用实色 primary;面状 hover/范围/斑马用 fill 层级
*
* === 本文区块 ===
* :root 亮色 / html.dark 暗色 / 运行时 theme.ts 覆盖
* 弹层、浮层 Popper、Select 选项、DatePicker 范围、级联、表格见对应注释
* 其余排期:Message、图表取 CSS 变量、登录全屏页;Tabs border-card 顶条 / Steps simple / Progress 轨道见下文
*/
:root,
html :root {
/* 基础中性色(画布/浅分割线轻混主色,随 --el-color-primary 略偏主题,保持淡淡层次) */
--el-bg-color: color-mix(in srgb, var(--el-color-primary, #4080ff) 5%, #f8fafc 95%);
--el-bg-color-page: var(--el-bg-color);
--el-bg-color-overlay: #ffffff;
--el-fill-color: #e2e8f0;
--el-fill-color-light: color-mix(in srgb, var(--el-color-primary, #4080ff) 3%, #f1f5f9 93%);
/* 亮色:分割线偏淡(主色比例略降、灰底偏浅) */
--el-border-color: color-mix(in srgb, var(--el-color-primary, #4080ff) 6%, #e2e8f0 94%);
--el-border-color-light: color-mix(in srgb, var(--el-color-primary, #4080ff) 7.5%, #eef2f7 92.5%);
--el-border-color-lighter: color-mix(in srgb, var(--el-color-primary, #4080ff) 15%, #f1f5f9 92%);
--el-border-color-extra-light: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 5.5%,
#f4f6f8 94.5%
);
--el-text-color-primary: #0f172a;
--el-text-color-regular: #475569;
--el-text-color-secondary: #64748b;
--el-text-color-placeholder: #94a3b8;
/* 阴影/遮罩 */
--el-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
--el-box-shadow-light: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--el-overlay-color: rgba(15, 23, 42, 0.5);
--el-overlay-color-light: rgba(15, 23, 42, 0.3);
--el-overlay-color-lighter: rgba(15, 23, 42, 0.15);
/* 菜单 hover 兼容 */
--el-menu-hover-bg-color: color-mix(in srgb, var(--el-color-primary, #4080ff) 8%, #f3f6fb 92%);
/* 全局原生滚动条:轨道浅底 + 滑块混主色(随 theme.ts / --el-color-primary 变) */
--app-scrollbar-track: color-mix(in srgb, var(--el-color-primary, #4080ff) 5%, #eef2f7 95%);
--app-scrollbar-thumb: color-mix(in srgb, var(--el-color-primary, #4080ff) 35%, #bcc8d4 65%);
--app-scrollbar-thumb-hover: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 48%,
#94a3b8 52%
);
/*
* 表格:表头 / 斑马 / 行悬停 — 同一主色,深浅分层(亮底;整体偏浅、主色占比低)
* 表头略深 → 悬停中等 → 斑马最浅
*/
--el-table-theme-header-bg: color-mix(in srgb, var(--el-color-primary, #4080ff) 8%, #f4f6f9 92%);
--el-table-theme-hover-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 5.5%,
var(--el-bg-color-overlay) 94.5%
);
--el-table-theme-stripe-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 4%,
var(--el-bg-color-overlay) 97%
);
/*
* 表格线:浅灰为主、主色极淡,避免格线抢眼(接近分割线「若有若无」)
*/
--el-table-theme-border-color: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 15.5%,
#eef2f7 95.5%
);
/* 画布/分割线交给 Element Plus:不再维护 layout-* 混色变量 */
/* Select / TreeSelect 选项行(EP 默认 hover=fill-light、选中无底,与主题脱节) */
--el-select-option-hover-bg: var(--el-fill-color-light);
--el-select-option-selected-bg: var(--el-color-primary-light-9);
/* DatePicker 区间内底(EP 默认 inrange≈极浅灰,与主题脱节) */
--el-datepicker-range-bg: var(--el-color-primary-light-9);
--el-datepicker-range-hover-bg: var(--el-color-primary-light-8);
/*
* 弹层
* - 遮罩:--el-overlay-color
* - 面板底:纯中性 overlay(不要混主色);主题色交给内部 primary 按钮、表单 focus、链接等
* - Drawer 继承 --el-dialog-bg-color;Dialog 见下方 html .el-dialog(压过 EP 的 var(--el-bg-color))
*/
--el-dialog-bg-color: var(--el-bg-color-overlay);
--el-popover-bg-color: var(--el-dialog-bg-color);
--el-popup-modal-bg-color: var(--el-overlay-color);
--el-popup-modal-opacity: 1;
}
html.dark {
/*
* 布局分区(仅暗色):侧栏主色略高 → 顶栏次之 → 主内容最淡(大面积阅读区)→ 卡片 overlay 略亮
*/
--layout-nav-bg: color-mix(in srgb, var(--el-color-primary, #4080ff) 6.5%, #101828 93.5%);
--layout-header-bg: color-mix(in srgb, var(--el-color-primary, #4080ff) 5%, #121a2a 95%);
--layout-content-bg: color-mix(in srgb, var(--el-color-primary, #4080ff) 4%, #0f172a 96%);
/* Logo 区与侧栏同一底(左侧布局下与 .layout__sidebar / --menu-background 一致,避免色差条) */
--layout-sidebar-logo-bg: var(--layout-nav-bg);
/* 卡片/表格面板:比主内容略「抬」一点 */
--el-bg-color-overlay: color-mix(in srgb, var(--el-color-primary, #4080ff) 6%, #1e293b 94%);
/* 基础中性色(画布 = 主内容区) */
--el-bg-color: var(--layout-content-bg);
--el-bg-color-page: var(--layout-content-bg);
--el-fill-color: #1e293b;
--el-fill-color-light: color-mix(in srgb, var(--el-color-primary, #4080ff) 8%, #334155 92%);
/* 暗色:缝隙/分割线略深一层,区划更清晰 */
--el-border-color: color-mix(in srgb, var(--el-color-primary, #4080ff) 14%, #334155 86%);
--el-border-color-light: color-mix(in srgb, var(--el-color-primary, #4080ff) 12%, #475569 88%);
--el-border-color-lighter: color-mix(in srgb, var(--el-color-primary, #4080ff) 13%, #3d4f69 87%);
--el-border-color-extra-light: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 11%,
#334155 89%
);
--el-text-color-primary: #f8fafc;
--el-text-color-regular: #e2e8f0;
--el-text-color-secondary: #94a3b8;
--el-text-color-placeholder: #64748b;
/* 阴影/遮罩 */
--el-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
--el-box-shadow-light: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
--el-overlay-color: rgba(0, 0, 0, 0.7);
--el-overlay-color-light: rgba(0, 0, 0, 0.5);
--el-overlay-color-lighter: rgba(0, 0, 0, 0.3);
/*
* 菜单 hover / 激活:真正颜色在 --_menu-*,再赋给 --el-menu-hover-bg-color。
* EP 在 el-menu 根上内联 --el-menu-hover-bg-color = TinyColor(bg).shade(20),会盖掉仅在 html 上的定义;
* 用下面 html.dark .el-menu { ... !important } 把同一套色压回组件根,子项即可用 EP 默认 hover。
*/
--_menu-hover-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 14%,
var(--layout-nav-bg) 86%
);
--_menu-active-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 21%,
var(--layout-nav-bg) 79%
);
--el-menu-hover-bg-color: var(--_menu-hover-bg);
--el-menu-active-bg-color: var(--_menu-active-bg);
/* 暗色全局滚动条:与主内容区协调,滑块略柔 */
--app-scrollbar-track: color-mix(in srgb, var(--el-color-primary, #4080ff) 7.5%, #0f172a 92.5%);
--app-scrollbar-thumb: color-mix(in srgb, var(--el-color-primary, #4080ff) 33%, #475569 67%);
--app-scrollbar-thumb-hover: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 46%,
#64748b 54%
);
/*
* 表格:暗底整体偏浅一档,主色占比降低,更接近面板底 --el-bg-color-overlay
*/
--el-table-theme-header-bg: color-mix(in srgb, var(--el-color-primary, #4080ff) 11%, #243044 89%);
--el-table-theme-hover-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 7.5%,
var(--el-bg-color-overlay) 92.5%
);
--el-table-theme-stripe-bg: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 4%,
var(--el-bg-color-overlay) 96%
);
/* 表格线:暗色下偏柔,与 overlay 接近、略亮一线即可辨认 */
--el-table-theme-border-color: color-mix(
in srgb,
var(--el-color-primary, #4080ff) 9%,
#3d4f63 91%
);
/* 画布/分割线/Tags hover 不再维护 layout-* 混色变量 */
--el-select-option-hover-bg: var(--el-fill-color-light);
--el-select-option-selected-bg: var(--el-color-primary-light-9);
--el-datepicker-range-bg: var(--el-color-primary-light-9);
--el-datepicker-range-hover-bg: var(--el-color-primary-light-8);
--el-dialog-bg-color: var(--el-bg-color-overlay);
--el-popover-bg-color: var(--el-dialog-bg-color);
--el-popup-modal-bg-color: var(--el-overlay-color);
--el-popup-modal-opacity: 1;
}
/* 压过 EP 内联的 shade(20),使子项 hover 读到与 html 一致的主题混色 */
html.dark .el-menu {
--el-menu-hover-bg-color: var(--_menu-hover-bg) !important;
}
/* Dialog:EP 在 .el-dialog 上写死 --el-dialog-bg-color: var(--el-bg-color),改为抬升中性底 */
html .el-dialog {
--el-dialog-bg-color: var(--el-bg-color-overlay);
}
/*
* 浮层 Popper(与弹窗同一 token:--el-dialog-bg-color,现为中性 overlay)
* EP 部分组件写死 --el-bg-color-overlay;显式统一到 --el-dialog-bg-color 便于后续改一处全局同步。
*/
html .el-cascader {
--el-cascader-menu-fill: var(--el-dialog-bg-color);
}
html .el-mention {
--el-mention-bg-color: var(--el-dialog-bg-color);
}
html .el-select__popper.el-popper,
html .el-tree-select__popper.el-popper,
html .el-dropdown__popper.el-popper,
html .el-autocomplete__popper.el-popper,
html .el-mention__popper.el-popper,
html .el-picker__popper.el-popper {
background: var(--el-dialog-bg-color);
}
html .el-select__popper.el-popper .el-popper__arrow:before,
html .el-tree-select__popper.el-popper .el-popper__arrow:before,
html .el-dropdown__popper.el-popper .el-popper__arrow:before,
html .el-autocomplete__popper.el-popper .el-popper__arrow:before,
html .el-mention__popper.el-popper .el-popper__arrow:before,
html .el-picker__popper.el-popper .el-popper__arrow:before {
background: var(--el-dialog-bg-color);
}
html .el-picker-panel {
background: var(--el-dialog-bg-color);
--el-datepicker-inrange-bg-color: var(--el-datepicker-range-bg);
--el-datepicker-inrange-hover-bg-color: var(--el-datepicker-range-hover-bg);
}
html .el-dropdown-menu {
background-color: var(--el-dialog-bg-color);
}
html .el-color-picker-panel {
background: var(--el-dialog-bg-color);
}
html .el-transfer-panel {
background: var(--el-dialog-bg-color);
}
/* Select / TreeSelect:选项 hover、选中背景随主色(浮层底仍为 overlay) */
html .el-select__popper .el-select-dropdown__item.is-hovering,
html .el-tree-select__popper .el-select-dropdown__item.is-hovering {
background-color: var(--el-select-option-hover-bg);
}
html .el-select__popper .el-select-dropdown__item.is-selected,
html .el-tree-select__popper .el-select-dropdown__item.is-selected {
background-color: var(--el-select-option-selected-bg);
}
/* 级联面板节点 hover 与 Select 一致(面板内自带 --el-cascader-node-background-hover) */
html .el-cascader-panel {
--el-cascader-node-background-hover: var(--el-select-option-hover-bg);
}
/* Skeleton 动画条:跟随中性 fill */
html .el-skeleton {
--el-skeleton-to-color: var(--el-fill-color);
}
/* Tabs border-card:使用中性 fill,避免混色 */
html .el-tabs--border-card > .el-tabs__header,
html.dark .el-tabs--border-card > .el-tabs__header {
background: var(--el-fill-color-light);
}
/* Steps 简约模式底条 */
html .el-steps--simple,
html.dark .el-steps--simple {
background: var(--el-fill-color-light);
}
/* Progress:轨道使用中性 fill */
html .el-progress-bar__outer,
html.dark .el-progress-bar__outer {
background-color: var(--el-fill-color-light);
}
/* ---------- Element Plus 表格(随 :root / html.dark 与 theme.ts 主色变) ---------- */
html .el-table {
--el-table-bg-color: var(--el-bg-color-overlay);
--el-table-tr-bg-color: var(--el-bg-color-overlay);
--el-table-header-bg-color: var(--el-table-theme-header-bg);
--el-table-striped-row-bg: var(--el-table-theme-stripe-bg);
--el-table-row-hover-bg-color: var(--el-table-theme-hover-bg);
--el-table-border-color: var(--el-table-theme-border-color);
--el-table-border: 1px solid var(--el-table-border-color);
}
html .el-table.el-table--striped {
--el-fill-color-lighter: var(--el-table-theme-stripe-bg);
}
/*
* Element Plus 自绘滚动条(el-scrollbar):侧栏菜单、表格 body、TagsView、分页等
* EP 默认 --el-scrollbar-bg-color 为 text-secondary + 低透明度,与主题无关;此处与上方「全局原生滚动条」同色
*/
html .el-scrollbar {
--el-scrollbar-bg-color: var(--app-scrollbar-thumb);
--el-scrollbar-hover-bg-color: var(--app-scrollbar-thumb-hover);
--el-scrollbar-opacity: 1;
--el-scrollbar-hover-opacity: 1;
}
-68
View File
@@ -1,68 +0,0 @@
$border: 1px solid var(--el-border-color-light);
/* el-dialog */
.el-dialog {
.el-dialog__header {
padding: 15px 20px;
margin: 0;
border-bottom: $border;
}
.el-dialog__body {
padding: 20px;
}
.el-dialog__footer {
padding: 15px;
border-top: $border;
}
}
/** el-drawer */
.el-drawer {
.el-drawer__header {
padding: 15px 20px;
margin: 0;
color: inherit;
border-bottom: $border;
}
.el-drawer__body {
padding: 20px;
}
.el-drawer__footer {
padding: 15px;
border-top: $border;
}
}
// 抽屉和对话框底部按钮区域
.dialog-footer {
display: flex;
gap: 8px;
justify-content: flex-end;
}
// 列表
.el-card {
.el-card__body {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
}
}
// 表格内操作列:单元格 .cell 默认 overflow:hidden,会裁切 el-button 的 :focus-visible outline(常见为底边缺失)。
// 仅对「含 el-button」的单元格放开裁剪,避免整表 .cell 全改为 visible 破坏省略号与长文本布局。
.el-table .el-table__cell .cell:has(.el-button) {
overflow: visible;
}
// 不支持 :has() 的环境:将 outline 略向内收,减轻裁切(效果弱于上一段)。
@supports not selector(:has(*)) {
.el-table .el-button:focus-visible {
outline-offset: -1px;
}
}
+16 -251
View File
@@ -1,258 +1,23 @@
// ==================== 主题变量导入 ====================
// 1. 项目自定义变量(侧边栏、布局等)
@use "./variables";
// 重置默认样式
@use './core/reset.scss';
// 2. 暗黑模式变量(合并)
@use "./dark/css-vars";
// 应用全局样式
@use './core/app.scss';
// ==================== 基础样式 ====================
@use "./reset";
@use "./element-plus";
// Element Plus 样式优化
@use './core/el-ui.scss';
// ==================== layout内容样式 ====================
.app-container {
display: flex;
flex-direction: column;
/* 不用 gap:否则 ExportModal/抽屉 等块级兄弟会与 PageContent 之间多出一道 16px,表格用 100vh 时高度也不对 */
gap: 0;
height: 100%;
padding: 16px;
overflow: auto;
border-radius: 4px;
}
// Element Plus 暗黑主题
@use './core/el-dark.scss';
/* 与搜索区纵向间距(替代原 gap);主表格占满剩余高度,便于 el-table height:100% */
.app-container > .el-card.data-table {
flex: 1;
min-height: 0;
margin-top: 16px;
}
// 暗黑主题样式优化
@use './core/dark.scss';
.app-container > .el-card.data-table:first-child {
margin-top: 0;
}
// 路由切换动画
@use './core/router-transition';
/* 用户管理等:首行是 el-row 时占满高度 */
.app-container > .el-row {
flex: 1;
min-height: 0;
}
// 主题切换过渡优化
@use './core/theme-change.scss';
/* 块级弹窗宿主不参与纵向 flex 分配,避免挤压主表格 */
.app-container > .curd-export-modal-host,
.app-container > .curd-import-modal-host {
flex: 0 0 auto;
}
// ==================== 搜索区域样式 ====================
.search-container {
border: 1px solid var(--el-border-color-light);
}
// ==================== 表格区域样式 ====================
.data-table {
display: flex;
flex-direction: column;
height: 100%;
/* 嵌套在 el-row/el-col 等内部时,与上方搜索区留白 */
margin-top: 16px;
// 表格工具栏区域(与 PageSearch+PageContent 各业务页 #toolbar 插槽一致:flex 换行,避免 el-row 挤压右侧)
&__toolbar {
display: flex;
flex-wrap: wrap;
row-gap: 8px;
column-gap: 12px;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 16px;
&--left,
&--right {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
@media (min-width: 768px) {
gap: 12px;
}
.el-button {
margin-right: 0 !important;
margin-left: 0 !important;
}
}
&--right {
flex-shrink: 0;
justify-content: flex-end;
}
}
// 表格内容区域
&__content {
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
margin: 0;
overflow: hidden;
transition:
height 0.3s ease,
flex 0.3s ease;
}
// 分页区域
.el-pagination {
justify-content: flex-end;
}
}
/* 主表格 margin-top 见上;此处保留嵌套在非直接子级时的默认 .data-table margin-top */
// 进度条颜色
#nprogress .bar {
background-color: var(--el-color-primary);
}
// ==================== 全局原生滚动条(与主题主色混色,Firefox + WebKit) ====================
* {
scrollbar-color: var(--app-scrollbar-thumb) var(--app-scrollbar-track);
scrollbar-width: thin;
}
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-track {
background: var(--app-scrollbar-track);
border-radius: 4px;
}
*::-webkit-scrollbar-thumb {
background: var(--app-scrollbar-thumb);
border-radius: 4px;
}
*::-webkit-scrollbar-thumb:hover {
background: var(--app-scrollbar-thumb-hover);
}
*::-webkit-scrollbar-corner {
background: var(--app-scrollbar-track);
}
// ==================== 菜单选中态(子菜单) ====================
// 给左侧/混合左侧以及顶部弹层子菜单的选中项增加背景色,增强可见性
.el-menu--vertical .el-menu-item.is-active,
.el-menu--popup .el-menu-item.is-active {
background-color: var(--el-color-primary-light-9) !important;
}
// ==================== 侧边栏激活项「右侧竖杠」指示条 ====================
// 仅作用于左侧布局、混合布局左侧侧栏(避免影响顶部菜单与弹层菜单)
.layout__sidebar,
.layout__sidebar--left {
.el-menu--vertical {
.el-menu-item.is-active {
box-shadow: inset -3px 0 0 0 var(--menu-active-indicator, var(--el-color-primary));
}
}
}
// 经典蓝:激活项背景不使用偏白色,改为蓝系轻色差背景
html.sidebar-color-blue {
.el-menu--vertical .el-menu-item.is-active,
.el-menu--popup .el-menu-item.is-active {
background-color: var(--menu-hover) !important;
}
}
// 混合布局左侧菜单 hover 不单独覆盖:
// 统一交给 Element Plus 的 --el-menu-hover-bg-color 与 MenuItem.vue 的通用规则,
// 确保 Mix-left 与 Left 侧边布局保持一致。
// 暗色:hover 由 EP + css-vars 中 html.dark .el-menu 覆写 --el-menu-hover-bg-color 生效;仅激活项需压过 primary-light-9
html.dark .el-menu--vertical .el-menu-item.is-active,
html.dark .el-menu--popup .el-menu-item.is-active {
background-color: var(--el-menu-active-bg-color) !important;
}
// 亮色 + 经典蓝:悬浮背景使用经典蓝体系(比底色略深),避免发白
html.sidebar-color-blue .el-menu {
.el-menu-item:hover,
.el-sub-menu__title:hover {
background-color: var(--menu-hover) !important;
}
}
html.sidebar-color-blue .el-menu--popup {
.el-menu-item:hover {
background-color: var(--menu-hover) !important;
}
}
// ==================== 窄屏时隐藏菜单文字,只显示图标 ====================
// 窄屏时隐藏菜单文字,只显示图标
.hideSidebar {
// Top布局和Mix布局的水平菜单
&.layout-top .layout__header .el-menu--horizontal,
&.layout-mix .layout__header .el-menu--horizontal {
.el-menu-item,
.el-sub-menu__title {
.menu-title,
span:not([class*="i-svg"]):not(.el-icon) {
display: none !important;
}
}
}
// Mix布局的左侧菜单
&.layout-mix .layout__sidebar--left .el-menu {
.el-menu-item,
.el-sub-menu__title {
.menu-title,
span:not([class*="i-svg"]):not(.el-icon) {
display: none !important;
}
}
}
}
// 代码生成:写入本地确认 — 随内容变宽(不超过视口),路径单行、列表区内横向滚动
.el-message-box.gencode-write-confirm-box {
--gencode-write-confirm-max: min(1100px, calc(100vw - 32px));
--el-messagebox-width: var(--gencode-write-confirm-max);
box-sizing: border-box;
width: fit-content !important;
min-width: min(360px, calc(100vw - 32px));
max-width: var(--gencode-write-confirm-max) !important;
padding-bottom: 8px;
.el-message-box__message {
box-sizing: border-box;
max-width: 100%;
padding-top: 4px;
}
.gencode-write-confirm-body {
min-width: 0;
max-width: 100%;
}
.gencode-write-path-list-wrap {
max-height: 44vh;
overflow: auto;
border: 1px solid var(--el-border-color-lighter);
border-radius: 8px;
box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
}
.gencode-write-path-row:last-child {
border-bottom: none !important;
}
}
// 主题切换圆形扩散动画
@use './core/theme-animation.scss';
-77
View File
@@ -1,77 +0,0 @@
*,
::before,
::after {
box-sizing: border-box;
border-color: currentcolor;
border-style: solid;
border-width: 0;
}
#app {
width: 100%;
height: 100%;
}
html {
box-sizing: border-box;
width: 100%;
height: 100%;
line-height: 1.5;
tab-size: 4;
text-size-adjust: 100%;
}
body {
width: 100%;
height: 100%;
margin: 0;
font-family:
"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑",
Arial, sans-serif;
line-height: inherit;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizelegibility;
}
a {
color: inherit;
text-decoration: inherit;
}
img,
svg {
display: inline-block;
}
svg {
// 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果
vertical-align: -0.15em;
}
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
a,
a:focus,
a:hover {
color: inherit;
text-decoration: none;
cursor: pointer;
}
a:focus,
a:active,
div:focus {
outline: none;
}
@@ -1,11 +0,0 @@
/* stylelint-disable property-no-unknown */
:export {
sidebar-width: $sidebar-width;
navbar-height: $navbar-height;
tags-view-height: $tags-view-height;
menu-background: $menu-background;
menu-text: $menu-text;
menu-active-text: $menu-active-text;
menu-hover: $menu-hover;
}
/* stylelint-enable property-no-unknown */
+7 -99
View File
@@ -1,100 +1,8 @@
@forward "element-plus/theme-chalk/src/common/var.scss" with (
$colors: (
"primary": (
// 默认主题色 - 修改此值时需同步修改 src/settings.ts 中的 themeColor
"base": #4080ff,
),
"success": (
"base": #23c343,
),
"warning": (
"base": #ff9a2e,
),
"danger": (
"base": #f76560,
),
"info": (
"base": #a9aeb8,
),
"default": (
"base": #f5f5f5,
),
),
/**
* 全局 SCSS 变量(由 vite.config.ts → css.preprocessorOptions.scss.additionalData 注入到每个 `.vue` 的 `lang="scss"`)
*
* 默认主色请与 `src/config/setting.ts` 中 `themeColorPresets` 首项、主题切换逻辑保持一致。
*/
$bg-color: (
"page": #f5f8fd,
)
);
/** 全局SCSS变量 */
:root {
--menu-background: #fff; // 菜单背景色
/* Logo 与侧栏导航同一底(亮色;暗色见 html.dark 与 css-vars --layout-nav-bg) */
--sidebar-logo-background: var(--menu-background);
--layout-logo-bg: var(--menu-background);
--menu-text: #212121; // 菜单文字颜色 浅色主题-白色侧边栏配色下仅占位,实际颜色由 el-menu-item 组件决定
--menu-active-text: var(
--el-menu-active-color
); // 菜单激活文字颜色 浅色主题-白色侧边栏配色下仅占位,实际颜色由 el-menu-item 组件决定
--menu-hover: #e6f4ff; // 菜单悬停背景色 浅色主题-白色侧边栏配色下仅占位,实际颜色由 el-menu-item 组件决定
--sidebar-logo-text-color: #333; // 侧边栏 Logo 文字颜色
}
/** 浅色主题-深蓝色侧边栏配色 */
html.sidebar-color-blue {
--menu-background: #304156; // 菜单背景色
--menu-text: #bfcbd9; // 菜单文字颜色
--menu-active-text: var(--el-menu-active-color); // 菜单激活文字颜色
--menu-hover: #263445; // 菜单悬停背景色
--el-menu-hover-bg-color: var(--menu-hover); // 顶部/侧边菜单 hover 统一
--sidebar-logo-text-color: #fff; // 侧边栏 Logo 文字颜色
}
/** 暗黑主题 */
html.dark {
/* 侧栏底:与主内容区分区,见 src/styles/dark/css-vars.css --layout-nav-bg */
--menu-background: var(--layout-nav-bg);
--menu-text: #fff;
--menu-active-text: var(--el-menu-active-color);
--menu-hover: var(--el-menu-hover-bg-color);
--sidebar-logo-background: var(--layout-sidebar-logo-bg);
--layout-logo-bg: var(--layout-sidebar-logo-bg);
--sidebar-logo-text-color: #fff;
/** WangEditor Dark */
/* Textarea - css vars */
--w-e-textarea-bg-color: var(--el-bg-color); /* 深色背景 */
--w-e-textarea-color: var(--el-text-color-primary); /* 浅色文字 */
--w-e-textarea-border-color: var(--el-border-color); /* 较深的边框颜色 */
--w-e-textarea-slight-border-color: var(--el-border-color-lighter); /* 更淡一些的边框颜色 */
--w-e-textarea-slight-color: var(--el-text-color-secondary); /* 浅灰色,用于不那么重要的元素 */
--w-e-textarea-slight-bg-color: var(--el-bg-color-overlay); /* 稍微亮一点的背景色 */
--w-e-textarea-selected-border-color: var(--el-color-info-light-5); /* 选中元素时的高亮边框 */
--w-e-textarea-handler-bg-color: var(--el-color-primary); /* 工具按钮或交互元素的背景色 */
/* Toolbar - css vars */
--w-e-toolbar-color: var(--el-text-color-regular); /* 工具栏文字颜色 */
--w-e-toolbar-bg-color: var(--el-bg-color); /* 工具栏背景颜色 */
--w-e-toolbar-active-color: var(--el-text-color-primary); /* 当前激活项的文字颜色 */
--w-e-toolbar-active-bg-color: var(--el-fill-color-light); /* 当前激活项的背景颜色 */
--w-e-toolbar-disabled-color: var(--el-text-color-secondary); /* 禁用项的颜色 */
--w-e-toolbar-border-color: var(--el-border-color-base); /* 工具栏边框颜色 */
/* Modal - css vars */
--w-e-modal-button-bg-color: var(--el-bg-color-light-3); /* 弹出框按钮背景色 */
--w-e-modal-button-border-color: var(--el-border-color-light); /* 弹出框按钮边框颜色 */
}
$menu-background: var(--menu-background); // 菜单背景色
$menu-text: var(--menu-text); // 菜单文字颜色
$menu-active-text: var(--menu-active-text); // 菜单激活文字颜色
$menu-hover: var(--menu-hover); // 菜单悬停背景色
$sidebar-logo-background: var(--sidebar-logo-background); // 侧边栏 Logo 背景色
$sidebar-logo-text-color: var(--sidebar-logo-text-color); // 侧边栏 Logo 文字颜色
$sidebar-width: 210px; // 侧边栏宽度
$sidebar-width-collapsed: 54px; // 侧边栏收缩宽度
$navbar-height: 50px; // 导航栏高度
$tags-view-height: 34px; // TagsView 高度
// 供组件内 `$primary-base` 等引用(可选)
$primary-base: #4080ff !default;