refactor(ui): 界面升级与代码规范优化

This commit is contained in:
Ray.Hao
2026-06-18 18:38:12 +08:00
parent 288ea9b43d
commit 14035cfa4d
130 changed files with 7813 additions and 5893 deletions

View File

@@ -1,68 +0,0 @@
/**
* 布局 Mixins
*
* 所有布局组件共享的样式抽象,确保单一来源。
*
* ═══════════════════════════════════════════════════════════
* 主题变量契约(添加新主题时必须定义以下 CSS 变量)
* ═══════════════════════════════════════════════════════════
*
* --menu-background 菜单背景色
* --menu-text 菜单文字色
* --menu-active-text 菜单激活文字色(通常复用 --el-menu-active-color)
* --menu-hover 菜单悬浮背景色【自动派生——见 _theme.scss 颜色令牌】
* --sidebar-logo-background Logo 区域背景色
* --sidebar-logo-text-color Logo 区域文字色
*
* 自动派生规则:--menu-hover 通过 color-mix() 从 --menu-background 派生,
* 因此新主题只需定义 --menu-background,hover 颜色自动生成。
* 如需覆盖自动派生值,显式设置 --menu-hover 即可。
*/
@use "variables" as *;
// ============================================
// 布局计算 Mixins
// ============================================
/**
* 计算主内容区高度(考虑 TagsView 是否存在)
*
* 使用场景:各布局文件中的 .hasTagsView 样式块
*
* @example
* .hasTagsView {
* :deep(.app-main) {
* @include app-main-height-with-tags;
* }
* }
*/
@mixin app-main-height-with-tags {
height: calc(100vh - $navbar-height - $tags-view-height) !important;
}
/**
* 主内容区基础高度(无 TagsView)
*
* @example
* .layout__main {
* @include app-main-height;
* }
*/
@mixin app-main-height {
height: calc(100vh - $navbar-height);
}
/**
* 侧边栏滚动区高度(带 Logo 时)
*/
@mixin sidebar-scroll-height-with-logo {
height: calc(100vh - $navbar-height);
}
/**
* 侧边栏滚动区高度(带底部折叠按钮时,如 MixLayout 左侧)
*/
@mixin sidebar-scroll-height-with-toggle {
height: calc(100vh - $navbar-height - $sidebar-toggle-height);
}

View File

@@ -1,94 +0,0 @@
/**
* 全局基础重置样式
* 补充 UnoCSS 预设未覆盖的项目级样式
*/
#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%;
}
#app,
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
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;
background-color: var(--page-bg);
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizelegibility;
}
/* 全局平滑滚动 */
html {
scroll-behavior: smooth;
}
/* 滚动条现代化 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-thumb {
background-color: rgb(0 0 0 / 12%);
border-radius: 3px;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
img,
svg {
display: inline-block;
}
svg {
// 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果
vertical-align: -0.15em;
}
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
a,
a:focus,
a:hover {
color: inherit;
text-decoration: none;
cursor: pointer;
}
a:focus,
a:active,
div:focus {
outline: none;
}

View File

@@ -1,140 +0,0 @@
/**
* 主题变量定义
*
* ═══════════════════════════════════════════════════════════
* 主题变量契约
* ═══════════════════════════════════════════════════════════
*
* 新增主题只需定义以下变量,其余自动派生:
*
* 必须定义:
* --menu-background 菜单背景色
* --menu-text 菜单文字色
* --menu-active-text 菜单激活文字色
* --sidebar-logo-background Logo 区域背景色
* --sidebar-logo-text-color Logo 区域文字色
*
* 可选覆盖(有自动派生默认值):
* --menu-hover 菜单悬浮背景色
* → 浅色主题:从 --el-color-primary 与背景混合派生
* → 深色主题:半透明黑色叠加层,自适应动态背景
* → 可显式覆盖以微调
*/
// ============================================
// SCSS 颜色令牌(构建时源)
// ============================================
$menu-bg-light: #fff;
$menu-hover-light: #e6f4ff; // 设计指定色,非纯推导
$menu-bg-classic-blue: #304156;
// ============================================
// 默认主题(浅色 + 白色侧边栏)
// ============================================
:root {
// 菜单
--menu-background: #{$menu-bg-light};
--menu-text: #606266;
--menu-active-text: var(--el-menu-active-color);
--menu-hover: #{$menu-hover-light};
// 侧边栏 Logo
--sidebar-logo-background: #fafafa;
--sidebar-logo-text-color: #383853;
// 页面背景与内容区
--page-bg: #fafbfc;
--content-bg: #ffffff;
// 边框
--border-color: #e2e8ee;
--card-border: rgb(0 0 0 / 8%);
// 卡片
--card-radius: calc(var(--custom-radius) + 4px);
--card-shadow: 0 1px 3px 0 rgb(0 0 0 / 6%), 0 1px 2px -1px rgb(0 0 0 / 4%);
// 全局圆角基准(可被 settings 动态覆盖)
--custom-radius: 8px;
// 页面布局间距
--page-padding: 20px;
--page-gap: 16px;
// 灰色阶
--gray-100: #f9fafb;
--gray-200: #f2f4f5;
--gray-300: #e6eaeb;
--gray-400: #dbdfe1;
--gray-500: #949eb7;
--gray-600: #7987a1;
--gray-700: #4d5875;
--gray-800: #383853;
--gray-900: #323251;
// 悬浮与激活
--hover-color: #edeff0;
--active-color: #f2f4f5;
}
// ============================================
// 深蓝色侧边栏主题
// ============================================
html.sidebar-color-blue {
--menu-background: #{$menu-bg-classic-blue};
--menu-text: #bfcbd9;
--menu-active-text: var(--el-menu-active-color);
// 自动派生:背景色加深 20% → #263445
--menu-hover: color-mix(in srgb, var(--menu-background) 80%, #000 20%);
--sidebar-logo-background: #2d3748;
--sidebar-logo-text-color: #fff;
}
// ============================================
// 暗黑主题
// ============================================
html.dark {
--menu-background: var(--el-bg-color-overlay);
--menu-text: #fff;
--menu-active-text: var(--el-menu-active-color);
// 半透明叠加层:自适应 Element Plus 动态 overlay 背景色
--menu-hover: rgb(0 0 0 / 20%);
--sidebar-logo-background: rgb(0 0 0 / 20%);
--sidebar-logo-text-color: #fff;
--page-bg: #070707;
--content-bg: #161618;
--border-color: rgb(255 255 255 / 10%);
--card-border: rgb(255 255 255 / 8%);
--card-shadow: 0 1px 3px 0 rgb(0 0 0 / 40%), 0 1px 2px -1px rgb(0 0 0 / 30%);
--gray-100: #110f0f;
--gray-200: #17171c;
--gray-300: #393946;
--gray-400: #505062;
--gray-500: #73738c;
--gray-600: #8f8fa3;
--gray-700: #ababba;
--gray-800: #c7c7d1;
--gray-900: #e3e3e8;
--hover-color: #252530;
--active-color: #202226;
.el-table {
--el-table-current-row-bg-color: var(--el-fill-color-light);
}
}
// ============================================
// 无障碍模式
// ============================================
html.color-weak {
filter: invert(80%);
}

View File

@@ -0,0 +1,355 @@
/**
* Element Plus 运行时样式覆盖
* 目标是把默认组件调成更轻、更清晰的中后台观感
*/
:root {
--el-border-radius-base: 6px;
--el-border-radius-small: 4px;
--el-font-weight-primary: 400;
--el-component-size: 34px;
--el-component-size-small: 28px;
--el-component-size-large: 38px;
--el-transition-duration: 0.16s;
--el-transition-duration-fast: 0.12s;
}
.el-card {
--el-card-border-color: var(--card-border);
--el-card-border-radius: var(--card-radius);
--el-card-padding: 18px;
overflow: hidden;
color: var(--el-text-color-primary);
border: 1px solid var(--card-border);
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
transition:
border-color 0.16s ease,
box-shadow 0.16s ease;
&.is-always-shadow,
&.is-hover-shadow:hover {
border-color: var(--card-border-hover);
box-shadow: var(--card-shadow-hover);
}
&.is-never-shadow {
box-shadow: var(--card-shadow);
}
.el-card__header {
padding: 14px 18px;
font-size: 14px;
font-weight: 500;
line-height: 1.4;
color: var(--el-text-color-primary);
border-bottom: 1px solid var(--card-border);
}
.el-card__body {
padding: var(--el-card-padding);
}
}
.el-input,
.el-select,
.el-date-editor {
--el-input-height: var(--el-component-size);
}
.el-input__wrapper,
.el-select__wrapper,
.el-textarea__inner {
background-color: var(--el-bg-color);
border-radius: 6px;
box-shadow: 0 0 0 1px var(--border-color) inset;
transition:
background-color 0.16s,
box-shadow 0.16s;
&:hover {
box-shadow: 0 0 0 1px var(--el-color-primary-light-5) inset;
}
&.is-focus,
&:focus,
&:focus-within {
box-shadow:
0 0 0 1px var(--el-color-primary) inset,
0 0 0 3px var(--el-color-primary-light-9);
}
}
.el-form--inline {
display: flex;
flex-wrap: wrap;
gap: 12px 16px;
align-items: center;
.el-form-item {
margin-right: 0;
margin-bottom: 0;
}
}
.el-form-item__label {
color: var(--el-text-color-regular);
}
.el-button {
--el-button-border-radius: 6px;
min-width: 34px;
font-weight: 400;
letter-spacing: 0;
box-shadow: none;
&:not(.is-link):not(.is-text) {
border-color: var(--border-color);
}
&:not(.is-link):not(.is-text):not(.el-button--large):not(.el-button--small) {
padding: 8px 14px;
}
&:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--el-color-primary-light-9);
}
}
.el-button--default {
background: var(--el-bg-color);
&:hover:not(.is-disabled),
&:focus:not(.is-disabled) {
color: var(--el-color-primary);
background: var(--el-color-primary-light-9);
border-color: var(--el-color-primary-light-5);
}
}
.el-button--primary,
.el-button--success,
.el-button--warning,
.el-button--danger {
border-color: transparent;
&:hover:not(.is-disabled) {
box-shadow: 0 6px 14px color-mix(in srgb, var(--el-button-bg-color) 28%, transparent);
filter: brightness(1.04);
}
}
.el-button.is-link {
min-width: auto;
padding: 0;
font-weight: 500;
}
.el-table {
--el-table-border-color: var(--border-color);
--el-table-header-bg-color: #f8fafc;
--el-table-row-hover-bg-color: #f8fbff;
--el-table-current-row-bg-color: #eef5ff;
--el-table-tr-bg-color: var(--el-bg-color);
overflow: hidden;
color: var(--el-text-color-primary);
border-radius: 6px;
&::before {
display: none;
}
&.el-table--border::after {
display: block;
background-color: var(--border-color);
}
.el-table__inner-wrapper::before {
height: 0;
}
.el-table__header th {
height: 44px;
padding: 0;
font-weight: 500;
color: var(--el-text-color-regular);
background: var(--el-table-header-bg-color);
border-bottom: 1px solid var(--border-color);
}
.el-table__body td {
height: 46px;
padding: 0;
border-bottom: 1px solid #eef1f6;
}
.cell {
line-height: 1.4;
}
.el-table__fixed-right {
box-shadow: -1px 0 0 var(--border-color);
}
&.is-empty {
.el-table__border-left-patch,
.el-table__border-right-patch,
.el-table__border-bottom-patch,
.el-table__fixed-right {
display: none;
}
.el-table__inner-wrapper::before,
&.el-table--border::before,
&.el-table--border::after,
&.el-table--border .el-table__inner-wrapper::after {
display: none;
}
.el-table__body td.el-table__cell {
border-right-color: transparent;
}
}
}
.el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: #fbfcff;
}
.el-pagination {
--el-pagination-button-height: 32px;
--el-pagination-button-width: 32px;
gap: 6px;
font-weight: 400;
.btn-prev,
.btn-next,
.el-pager li {
border: 1px solid var(--border-color);
border-radius: 6px;
}
.el-pager li.is-active {
border-color: var(--el-color-primary);
box-shadow: 0 6px 14px rgb(22 93 255 / 18%);
}
}
.el-tag {
height: 24px;
padding: 0 8px;
font-weight: 400;
border: none;
border-radius: 4px;
}
.el-tree {
--el-tree-node-hover-bg-color: var(--el-color-primary-light-9);
color: var(--el-text-color-regular);
.el-tree-node__content {
height: 34px;
padding-right: 8px;
border-radius: 6px;
transition:
color 0.16s,
background-color 0.16s;
}
.el-tree-node:focus > .el-tree-node__content,
.el-tree-node.is-current > .el-tree-node__content {
color: var(--el-color-primary);
background-color: var(--el-color-primary-light-9);
}
}
.el-dialog {
overflow: hidden;
border-radius: 8px;
box-shadow: 0 18px 48px rgb(15 23 42 / 18%);
.el-dialog__header {
padding: 18px 20px 12px;
margin: 0;
border-bottom: 1px solid var(--border-color);
}
.el-dialog__body {
padding: 20px;
}
.el-dialog__footer {
padding: 14px 20px;
border-top: 1px solid var(--border-color);
}
}
.el-drawer {
.el-drawer__header {
padding: 16px 20px;
margin: 0;
color: var(--el-text-color-primary);
border-bottom: 1px solid var(--border-color);
}
.el-drawer__body {
padding: 20px;
}
.el-drawer__footer {
padding: 14px 16px;
border-top: 1px solid var(--border-color);
}
}
.el-dropdown-menu__item,
.el-select-dropdown__item {
margin: 2px 6px;
border-radius: 6px;
}
.el-menu--popup {
--el-menu-bg-color: var(--menu-background);
--el-menu-text-color: var(--menu-text);
--el-menu-active-color: var(--menu-active-text);
--el-menu-hover-bg-color: var(--menu-hover);
background-color: var(--menu-background);
border-radius: 8px;
.el-menu-item,
.el-sub-menu__title {
color: var(--menu-text) !important;
}
.el-menu-item:hover,
.el-sub-menu__title:hover {
color: var(--menu-active-text) !important;
background-color: var(--menu-hover) !important;
}
.el-menu-item.is-active {
color: var(--menu-active-text) !important;
background-color: var(--menu-hover) !important;
}
}
html.dark {
.el-table {
--el-table-header-bg-color: #171b22;
--el-table-row-hover-bg-color: rgb(22 93 255 / 10%);
--el-table-current-row-bg-color: rgb(22 93 255 / 14%);
.el-table__body td {
border-bottom-color: rgb(255 255 255 / 8%);
}
}
.el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: rgb(255 255 255 / 2%);
}
}

View File

@@ -0,0 +1,30 @@
/**
* Element Plus Sass 主题变量配置
*
* 通过 vite.config.ts 的 additionalData 注入,必须在 Element Plus 组件 Sass
* 样式加载前生效。
*/
@forward "element-plus/theme-chalk/src/common/var.scss" with (
$colors: (
"primary": (
// 与 src/settings.ts 的默认色板保持一致,避免首屏出现两套颜色。
"base": #165dff,
),
"success": (
"base": #00b42a,
),
"warning": (
"base": #ff7d00,
),
"danger": (
"base": #f53f3f,
),
"info": (
"base": #86909c,
),
),
$bg-color: (
"page": #f5f7fb,
)
);

View File

@@ -1,19 +1,15 @@
/**
* 样式总入口
* 严格按照 ITCSS 架构顺序导入
*/
// 1. 基础层
@use "./base/variables" as *;
@use "./base/theme";
@use "./base/reset";
// 1. 基础与主题层
@use "./theme";
@use "./reset";
// 2. 第三方适配层
@use "./vendors/element-plus";
@use "./vendors/element-plus-override";
@use "./vendors/vxe-table";
@use "./vendors/wangeditor";
@use "./vendors/nprogress";
@use "./element-plus-overrides";
@use "./vendors";
// 3. 布局层
@use "./layout/layout";
// 3. 布局与页面层
@use "./menu";
@use "./page";

View File

@@ -1,57 +1,8 @@
/**
* 全局标准布局样式
* 菜单交互样式
*/
.page-container {
padding: var(--page-padding);
}
.page-aside {
margin-bottom: var(--page-gap);
@media (min-width: 992px) {
margin-bottom: 0;
}
}
.page-main {
display: flex;
flex-direction: column;
gap: var(--page-gap);
}
.page-search {
margin-bottom: var(--page-gap);
.el-card__body {
padding: 14px 16px 4px;
}
.el-form-item {
margin-bottom: 10px;
}
}
.page-content {
display: flex;
flex: 1;
flex-direction: column;
}
.page-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--page-gap);
&__left,
&__right {
display: flex;
gap: 8px;
}
}
/* 混合布局左侧菜单 hover 样式 */
// 混合布局左侧菜单 hover
.layout-mix .layout__sidebar--left .el-menu {
.el-menu-item:hover,
.el-sub-menu__title:hover {
@@ -59,16 +10,23 @@
}
}
/* 深色或深蓝侧边栏的 hover 样式 */
// 深色或深蓝侧边栏的 hover
html.dark .layout-mix .layout__sidebar--left .el-menu,
html.sidebar-color-blue .layout-mix .layout__sidebar--left .el-menu {
.el-menu-item:hover,
.el-sub-menu__title:hover {
background-color: var(--menu-hover) !important;
}
.el-menu-item.is-active,
.el-sub-menu.is-active > .el-sub-menu__title,
.el-sub-menu.has-active-child > .el-sub-menu__title {
color: var(--menu-active-text) !important;
background-color: var(--menu-active-bg) !important;
}
}
/* 顶部布局菜单填充空间 */
// 顶部布局菜单填充空间
.layout-top .layout__header-left .el-menu--horizontal,
.layout-mix .layout__header-menu .el-menu--horizontal {
display: flex;
@@ -79,7 +37,7 @@ html.sidebar-color-blue .layout-mix .layout__sidebar--left .el-menu {
overflow: hidden;
}
/* 窄屏隐藏菜单文字,仅保留图标 */
// 窄屏隐藏菜单文字,仅保留图标
.hideSidebar {
&.layout-top .layout__header .el-menu--horizontal,
&.layout-mix .layout__header .el-menu--horizontal {

21
src/styles/mixins.scss Normal file
View File

@@ -0,0 +1,21 @@
/**
* 布局 Mixins
*/
@use "variables" as *;
@mixin app-main-height-with-tags {
height: calc(100vh - $navbar-height - $tags-view-height) !important;
}
@mixin app-main-height {
height: calc(100vh - $navbar-height);
}
@mixin sidebar-scroll-height-with-logo {
height: calc(100vh - $navbar-height);
}
@mixin sidebar-scroll-height-with-toggle {
height: calc(100vh - $navbar-height - $sidebar-toggle-height);
}

111
src/styles/page.scss Normal file
View File

@@ -0,0 +1,111 @@
/**
* 页面公共样式
*/
.page-container {
display: flex;
flex-direction: column;
gap: var(--page-gap);
height: 100%;
min-height: 0;
padding: var(--page-padding);
background: var(--page-bg);
}
.page-search {
flex-shrink: 0;
.el-card__body {
padding: 12px 16px;
}
.el-form-item {
margin-bottom: 0;
}
}
.page-content {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
overflow: hidden;
.el-card__body {
display: grid;
flex: 1 1 auto;
grid-template-rows: auto minmax(0, 1fr) auto;
min-height: 0;
padding: 12px 16px;
overflow: hidden;
}
}
.page-toolbar {
display: flex;
flex-shrink: 0;
gap: 12px;
align-items: center;
justify-content: space-between;
margin-bottom: var(--page-gap);
&__left,
&__right {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
.el-button {
margin: 0;
}
}
&__right {
justify-content: flex-end;
margin-left: auto;
}
}
.page-table-wrapper {
min-height: 0;
overflow: hidden;
background: var(--content-bg);
border: 1px solid var(--border-color);
border-radius: var(--card-radius);
}
.page-table {
width: 100%;
height: 100%;
min-height: 0;
border-radius: 0;
&.el-table--border {
border: 0;
}
.el-table__inner-wrapper {
height: 100%;
}
}
.page-pagination {
flex-shrink: 0;
}
.page-icon-btn {
width: 32px;
height: 32px;
padding: 0;
&.el-button + .el-button {
margin-left: 0;
}
}
.dialog-footer {
display: flex;
gap: 8px;
justify-content: flex-end;
}

45
src/styles/reset.scss Normal file
View File

@@ -0,0 +1,45 @@
html,
body,
#app {
width: 100%;
height: 100%;
}
html {
box-sizing: border-box;
line-height: 1.5;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
margin: 0;
font-family:
Inter, system-ui, Avenir, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-thumb {
background-color: rgb(0 0 0 / 12%);
border-radius: 3px;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
a {
color: inherit;
text-decoration: none;
}

62
src/styles/theme.scss Normal file
View File

@@ -0,0 +1,62 @@
/**
* 主题变量定义
*/
// 浅色主题
:root {
--menu-background: #fff;
--menu-text: #606266;
--menu-active-text: var(--el-menu-active-color);
--menu-active-bg: #e8f3ff;
--menu-hover: #e6f4ff;
--menu-border: var(--card-border);
--sidebar-logo-background: #fafafa;
--sidebar-logo-text-color: #383853;
--page-bg: #f6f8fc;
--content-bg: #ffffff;
--border-color: #e3eaf3;
--card-border: #dfe7f1;
--card-border-hover: #d5dfec;
--card-radius: 8px;
--card-shadow: 0 1px 2px rgb(15 23 42 / 3%);
--card-shadow-hover: 0 10px 24px rgb(15 23 42 / 6%), 0 2px 6px rgb(15 23 42 / 4%);
--custom-radius: 8px;
--page-padding: 10px;
--page-gap: 10px;
}
// 深蓝色侧边栏
html.sidebar-color-blue {
--menu-background: #304156;
--menu-text: #bfcbd9;
--menu-active-text: #ffffff;
--menu-active-bg: rgb(22 93 255 / 18%);
--menu-hover: rgb(255 255 255 / 7%);
--menu-border: rgb(15 23 42 / 22%);
--sidebar-logo-background: #2d3748;
--sidebar-logo-text-color: #fff;
}
// 暗黑主题
html.dark {
--menu-background: var(--el-bg-color-overlay);
--menu-text: #fff;
--menu-active-text: #ffffff;
--menu-active-bg: rgb(22 93 255 / 16%);
--menu-hover: rgb(0 0 0 / 20%);
--menu-border: rgb(255 255 255 / 8%);
--sidebar-logo-background: rgb(0 0 0 / 20%);
--sidebar-logo-text-color: #fff;
--page-bg: #0d1117;
--content-bg: #161618;
--border-color: rgb(255 255 255 / 10%);
--card-border: rgb(255 255 255 / 10%);
--card-border-hover: rgb(255 255 255 / 14%);
--card-shadow: none;
--card-shadow-hover: none;
}
// 无障碍模式
html.color-weak {
filter: invert(80%);
}

View File

@@ -1,18 +1,14 @@
/* stylelint-disable property-no-unknown */
// SCSS 变量导出给 JS/TS
// 通过 SCSS 变量导出给 JS/TS 使用的模块文件
// 注意:依赖 src/styles/base/_variables.scss 中定义的 SCSS 变量
@use "./base/variables" as *;
@use "./variables" as *;
: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 */

View File

@@ -1,22 +1,17 @@
/**
* SCSS 变量定义
* 只放数学变量和 CSS 变量映射
*/
// ============================================
// 布局尺寸变量
// ============================================
// 布局尺寸
$sidebar-width: 210px;
$sidebar-width-collapsed: 54px;
$navbar-height: 50px;
$tags-view-height: 40px;
$sidebar-primary-width: 76px;
$sidebar-secondary-width: 210px;
$navbar-height: 48px;
$tags-view-height: 38px;
$sidebar-toggle-height: 50px;
// ============================================
// CSS 变量映射(供组件和 SCSS 使用)
// ============================================
// 菜单配色(映射 theme.scss 的 CSS 变量)
$menu-background: var(--menu-background);
$menu-text: var(--menu-text);
$menu-active-text: var(--menu-active-text);

View File

@@ -1,12 +1,14 @@
/**
* Vxe Table 主题统一:
* 1) 用 Element Plus 的 CSS 变量覆写 Vxe Table 的 CSS 变量
* 2) 自定义局部样式
* 第三方组件样式适配
*/
/* 变量覆写 */
// NProgress 进度条样式
#nprogress .bar {
background-color: var(--el-color-primary);
}
// VxeTable 变量覆写
:root {
/* color */
--vxe-font-color: var(--el-text-color-regular);
--vxe-primary-color: var(--el-color-primary);
--vxe-success-color: var(--el-color-success);
@@ -31,17 +33,11 @@
--vxe-info-disabled-color: var(--el-color-info-light-5);
--vxe-warning-disabled-color: var(--el-color-warning-light-5);
--vxe-danger-disabled-color: var(--el-color-danger-light-5);
/* input/radio/checkbox */
--vxe-input-border-color: var(--el-border-color);
--vxe-input-disabled-color: var(--el-text-color-disabled);
--vxe-input-disabled-background-color: var(--el-fill-color-light);
--vxe-input-placeholder-color: var(--el-text-color-placeholder);
/* popup */
--vxe-table-popup-border-color: var(--el-border-color);
/* table */
--vxe-table-header-font-color: var(--el-text-color-regular);
--vxe-table-footer-font-color: var(--el-text-color-regular);
--vxe-table-border-color: var(--el-border-color-lighter);
@@ -52,81 +48,71 @@
--vxe-table-row-current-background-color: var(--el-fill-color-light);
--vxe-table-row-hover-current-background-color: var(--el-fill-color-light);
--vxe-table-checkbox-range-background-color: var(--el-fill-color-light);
/* menu */
--vxe-table-menu-background-color: var(--el-bg-color-overlay);
/* loading */
--vxe-loading-color: var(--el-color-primary);
--vxe-loading-background-color: var(--el-mask-color);
/* validate */
--vxe-table-validate-error-color: var(--el-color-danger);
/* toolbar */
--vxe-toolbar-background-color: var(--el-bg-color);
--vxe-toolbar-custom-active-background-color: var(--el-bg-color-overlay);
--vxe-toolbar-panel-background-color: var(--el-bg-color-overlay);
/* pager */
--vxe-pager-background-color: var(--el-bg-color);
/* modal */
--vxe-modal-header-background-color: var(--el-bg-color);
--vxe-modal-body-background-color: var(--el-bg-color);
--vxe-modal-border-color: var(--el-border-color);
/* button */
--vxe-button-default-background-color: var(--el-bg-color-overlay);
/* input */
--vxe-input-background-color: var(--el-fill-color-blank);
--vxe-input-panel-background-color: var(--el-fill-color-blank);
/* form */
--vxe-form-background-color: var(--el-bg-color);
--vxe-form-validate-error-color: var(--el-color-danger);
/* select */
--vxe-select-option-hover-background-color: var(--el-bg-color-overlay);
--vxe-select-panel-background-color: var(--el-bg-color);
}
/* 自定义组件样式 */
// VxeTable 自定义样式
.vxe-grid {
/* 表单 */
&--form-wrapper {
.vxe-form {
padding: 10px 20px;
margin-bottom: 20px;
}
&--form-wrapper .vxe-form {
padding: 10px 20px;
margin-bottom: 20px;
}
/* 工具栏 */
&--toolbar-wrapper {
.vxe-toolbar {
padding: 20px;
}
&--toolbar-wrapper .vxe-toolbar {
padding: 20px;
}
/* 分页 */
&--pager-wrapper {
.vxe-pager {
height: 70px;
padding: 0 20px;
&--pager-wrapper .vxe-pager {
height: 70px;
padding: 0 20px;
&--wrapper {
/* 参考 Bootstrap 的响应式设计 WIDTH = 768 */
@media screen and (width <= 768px) {
.vxe-pager--total,
.vxe-pager--sizes,
.vxe-pager--jump,
.vxe-pager--jump-prev,
.vxe-pager--jump-next {
display: none;
}
&--wrapper {
@media screen and (width <= 768px) {
.vxe-pager--total,
.vxe-pager--sizes,
.vxe-pager--jump,
.vxe-pager--jump-prev,
.vxe-pager--jump-next {
display: none;
}
}
}
}
}
// WangEditor 暗黑模式
html.dark {
--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);
--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);
--w-e-modal-button-bg-color: var(--el-bg-color-overlay);
--w-e-modal-button-border-color: var(--el-border-color-light);
}

View File

@@ -1,186 +0,0 @@
/**
* Element Plus 组件样式定制
*/
$border: 1px solid var(--border-color);
/* 全局组件圆角基准 */
:root {
--el-border-radius-base: 6px;
--el-border-radius-small: 4px;
--el-font-weight-primary: 400;
}
/* 卡片 — 边框模式 */
.el-card {
border: 1px solid var(--card-border);
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
transition: box-shadow 0.2s ease;
&:hover {
box-shadow:
0 4px 12px 0 rgb(0 0 0 / 8%),
0 1px 3px 0 rgb(0 0 0 / 4%);
}
.el-card__header {
padding: 16px 20px;
border-bottom: 1px solid var(--card-border);
}
.el-card__body {
padding: 20px;
}
}
/* 弹窗 */
.el-dialog {
border-radius: 12px;
.el-dialog__header {
padding: 20px 20px 0;
margin: 0;
border-bottom: none;
}
.el-dialog__body {
padding: 20px;
}
.el-dialog__footer {
padding: 0 20px 20px;
border-top: none;
}
}
/* 抽屉 */
.el-drawer {
.el-drawer__header {
padding: 16px 20px;
margin: 0;
color: inherit;
border-bottom: $border;
}
.el-drawer__body {
padding: 20px;
}
.el-drawer__footer {
padding: 16px;
border-top: $border;
}
}
/* el-table */
.el-table {
--el-table-border-color: var(--border-color);
--el-table-header-bg-color: var(--gray-100);
--el-table-row-hover-bg-color: var(--el-fill-color-lighter);
--el-table-current-row-bg-color: var(--el-fill-color-light);
border-radius: var(--custom-radius);
/* 表头 */
.el-table__header th {
padding: 12px 0;
font-weight: 500;
color: var(--el-text-color-regular);
border-bottom: 1px solid var(--border-color);
}
/* 单元格 */
.el-table__body td {
padding: 10px 0;
}
/* 无数据时不显示底部边框 */
.el-table__empty-block {
border-bottom: none;
}
}
/* 斑马纹 — 更柔和 */
.el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: rgb(0 0 0 / 1.5%);
}
html.dark .el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: rgb(255 255 255 / 2%);
}
/* 下拉菜单项 */
.el-dropdown-menu__item,
.el-select-dropdown__item {
margin: 2px 6px;
border-radius: 6px;
}
/* 按钮 */
.el-button {
--el-button-border-radius: var(--el-border-radius-base);
letter-spacing: 0.01em;
&:not(.is-link):not(.el-button--large):not(.el-button--small) {
padding: 9px 16px;
}
}
.el-button--default {
--el-button-border-color: var(--border-color);
&:hover:not(.is-disabled) {
color: var(--el-color-primary);
background: var(--el-color-primary-light-9);
border-color: var(--el-color-primary-light-5);
}
}
.el-button--primary,
.el-button--success,
.el-button--warning,
.el-button--danger {
&:hover:not(.is-disabled) {
box-shadow: 0 2px 6px 0 var(--el-button-bg-color);
}
}
/* 标签 */
.el-tag {
border-radius: 4px;
}
/* 抽屉和对话框底部按钮区域 */
.dialog-footer {
display: flex;
gap: 8px;
justify-content: flex-end;
}
/* 弹出菜单统一使用主题变量 */
.el-menu--popup {
--el-menu-bg-color: var(--menu-background);
--el-menu-text-color: var(--menu-text);
--el-menu-active-color: var(--menu-active-text);
--el-menu-hover-bg-color: var(--menu-hover);
background-color: var(--menu-background);
border-radius: 8px;
.el-menu-item,
.el-sub-menu__title {
color: var(--menu-text) !important;
}
.el-menu-item:hover,
.el-sub-menu__title:hover {
color: var(--menu-active-text) !important;
background-color: var(--menu-hover) !important;
}
.el-menu-item.is-active {
color: var(--menu-active-text) !important;
background-color: var(--menu-hover) !important;
}
}

View File

@@ -1,28 +0,0 @@
/**
* Element Plus 主题变量覆盖
* 必须在组件样式之前导入
*/
@forward "element-plus/theme-chalk/src/common/var.scss" with (
$colors: (
"primary": (
// 默认主题色 - 修改此值时需同步修改 src/settings.ts 中的 themeColor
"base": #1677ff,
),
"success": (
"base": #22c55e,
),
"warning": (
"base": #faad14,
),
"danger": (
"base": #ff4d4f,
),
"info": (
"base": #788896,
),
),
$bg-color: (
"page": #f5f8fd,
)
);

View File

@@ -1,7 +0,0 @@
/**
* NProgress 进度条样式
*/
#nprogress .bar {
background-color: var(--el-color-primary);
}

View File

@@ -1,28 +0,0 @@
/**
* WangEditor 暗黑模式适配
* 使用 Element Plus CSS 变量实现主题统一
*/
html.dark {
/* Textarea */
--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 */
--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 */
--w-e-modal-button-bg-color: var(--el-bg-color-light-3);
--w-e-modal-button-border-color: var(--el-border-color-light);
}