重构代理池系统:简化架构并增强核心功能

后端变更:
- 移除 tasks_manager.py 和 core/auth.py,简化架构
- 新增 core/scheduler.py 验证调度器,替代原有任务管理
- 大幅优化 api_server.py:统一错误处理、增强参数验证、支持调度器控制
- validator.py 增强 SOCKS4/SOCKS5 代理验证支持
- config.py 清理废弃配置(WebSocket、API Key、认证开关)
- SQLite 数据库操作性能优化

前端变更:
- 移除任务管理页面 (CrawlerTasks) 和 WebSocket 相关代码
- 路由简化为 4 个核心页面:总览、代理列表、插件管理、设置
- 提取前端工具函数(clipboard、confirm、format)和 API 类型定义
- 优化 CSS 架构:完善 variables、utilities、element-plus 样式
- Dashboard、Plugins、ProxyList、Settings 页面 UI/UX 优化
- App.vue 响应式侧边栏和页面过渡动画优化

其他:
- 移除 PowerShell 启动脚本,简化 Windows 批处理脚本
- 新增 README_SOCKS.md SOCKS 代理支持文档
- .env.example 和 .gitignore 更新
This commit is contained in:
祀梦
2026-04-02 11:23:23 +08:00
parent b5932a95b2
commit a79f78b338
47 changed files with 3748 additions and 3190 deletions

View File

@@ -1,5 +1,10 @@
/* ==================== Element Plus 冷灰紫主题覆盖 ==================== */
/* -------------------- 输入框 -------------------- */
.el-input__wrapper {
background-color: var(--surface-3) !important;
box-shadow: 0 0 0 1px var(--border) inset !important;
border-radius: var(--radius-md) !important;
}
.el-input__wrapper:hover,
@@ -7,8 +12,23 @@
box-shadow: 0 0 0 1px var(--primary) inset !important;
}
.el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px var(--primary) inset, var(--shadow-primary-sm) !important;
}
.el-input__inner {
color: var(--text-primary) !important;
}
.el-input__inner::placeholder {
color: var(--text-muted) !important;
}
/* -------------------- 选择器 -------------------- */
.el-select__wrapper {
background-color: var(--surface-3) !important;
box-shadow: 0 0 0 1px var(--border) inset !important;
border-radius: var(--radius-md) !important;
}
.el-select__wrapper:hover,
@@ -16,55 +36,67 @@
box-shadow: 0 0 0 1px var(--primary) inset !important;
}
.el-select__wrapper.is-focused {
box-shadow: 0 0 0 1px var(--primary) inset, var(--shadow-primary-sm) !important;
}
.el-select__placeholder {
color: var(--text-secondary) !important;
color: var(--text-muted) !important;
}
.el-select__caret {
color: var(--text-secondary) !important;
}
.el-select__caret.is-reverse {
color: var(--primary) !important;
}
.el-select-dropdown {
border: 1px solid var(--border) !important;
box-shadow: var(--shadow-md) !important;
background: white !important;
box-shadow: var(--shadow-lg) !important;
background: var(--surface) !important;
border-radius: var(--radius-md) !important;
}
.el-select-dropdown__item {
color: var(--text-primary) !important;
color: var(--text-secondary) !important;
}
.el-select-dropdown__item:hover {
background: rgba(255, 107, 157, 0.1) !important;
background: var(--primary-soft) !important;
color: var(--primary) !important;
}
.el-select-dropdown__item.is-selected {
color: var(--primary) !important;
font-weight: 600;
background: var(--primary-soft) !important;
}
/* -------------------- 数字输入框 -------------------- */
.el-input-number__decrease,
.el-input-number__increase {
background: var(--bg-light) !important;
background: var(--surface-2) !important;
color: var(--text-secondary) !important;
border: 1px solid var(--border) !important;
}
.el-input-number__decrease:hover,
.el-input-number__increase:hover {
background: rgba(255, 107, 157, 0.1) !important;
background: var(--primary-soft) !important;
color: var(--primary) !important;
border-color: var(--primary) !important;
}
.el-input-number__decrease.is-disabled,
.el-input-number__increase.is-disabled {
color: #ccc !important;
color: var(--el-disabled-text) !important;
border-color: var(--border) !important;
}
.el-input-number__wrapper {
background-color: var(--surface-3) !important;
box-shadow: 0 0 0 1px var(--border) inset !important;
}
@@ -73,79 +105,132 @@
box-shadow: 0 0 0 1px var(--primary) inset !important;
}
/* -------------------- 按钮 -------------------- */
.el-button {
border: 1px solid var(--border) !important;
background: var(--surface-2) !important;
color: var(--text-secondary) !important;
border-radius: var(--radius-md) !important;
font-weight: 500;
}
.el-button--primary {
background: var(--gradient-primary) !important;
.el-button:hover {
border-color: var(--primary) !important;
color: var(--primary) !important;
background: var(--surface-3) !important;
}
/* 主要按钮 - 深紫实心 */
.el-button--primary {
background: var(--primary-solid) !important;
border-color: var(--primary-solid) !important;
color: white !important;
}
.el-button--primary:hover {
box-shadow: 0 4px 12px rgba(255, 107, 157, 0.3) !important;
transform: translateY(-2px);
background: var(--primary-solid-hover) !important;
border-color: var(--primary-solid-hover) !important;
box-shadow: var(--shadow-primary-md) !important;
transform: translateY(-1px);
}
/* 成功按钮 - 青绿 */
.el-button--success {
background: var(--gradient-cyan) !important;
border-color: var(--cyan) !important;
color: white !important;
background: var(--success) !important;
border-color: var(--success) !important;
color: var(--bg) !important;
}
.el-button--success:hover {
box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3) !important;
transform: translateY(-2px);
background: #2DD4BF !important;
border-color: #2DD4BF !important;
box-shadow: 0 0 20px rgba(34, 197, 94, 0.3) !important;
}
/* 警告按钮 - 橙黄 */
.el-button--warning {
background: var(--gradient-yellow) !important;
border-color: var(--yellow) !important;
color: white !important;
background: var(--warning) !important;
border-color: var(--warning) !important;
color: var(--bg) !important;
}
.el-button--warning:hover {
box-shadow: 0 4px 12px rgba(255, 184, 0, 0.3) !important;
transform: translateY(-2px);
background: #FBBF24 !important;
border-color: #FBBF24 !important;
box-shadow: 0 0 20px rgba(245, 158, 11, 0.3) !important;
}
/* 危险按钮 - 粉红 */
.el-button--danger {
background: var(--gradient-danger) !important;
background: var(--danger) !important;
border-color: var(--danger) !important;
color: white !important;
}
.el-button--danger:hover {
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3) !important;
transform: translateY(-2px);
background: #FCA5A5 !important;
border-color: #FCA5A5 !important;
box-shadow: 0 0 20px rgba(251, 113, 133, 0.3) !important;
}
/* 纯文字按钮 */
.el-button--text {
background: transparent !important;
border-color: transparent !important;
color: var(--primary) !important;
}
.el-button--text:hover {
color: var(--primary-hover) !important;
background: var(--primary-soft) !important;
}
/* -------------------- 卡片 -------------------- */
.el-card {
border: 1px solid var(--border) !important;
box-shadow: var(--shadow-sm) !important;
box-shadow: none !important;
background: var(--surface) !important;
border-radius: var(--radius-lg) !important;
}
.el-card:hover {
border-color: var(--border-light) !important;
}
.el-card__header {
border-bottom: 1px solid var(--border) !important;
padding: 16px 20px;
}
.el-card__body {
background: var(--bg-card) !important;
background: transparent !important;
padding: 20px;
}
/* -------------------- 表格 -------------------- */
.el-table {
border: 1px solid var(--border) !important;
background: white !important;
background: var(--surface) !important;
border-radius: var(--radius-lg) !important;
--el-table-row-hover-bg-color: var(--surface-2);
--el-table-current-row-bg-color: var(--primary-soft);
--el-table-header-bg-color: var(--surface-2);
--el-table-tr-bg-color: var(--surface);
--el-table-expanded-cell-bg-color: var(--surface);
}
.el-table th.el-table__cell {
background: var(--bg-light) !important;
color: var(--text-primary) !important;
background: var(--surface-2) !important;
color: var(--text-secondary) !important;
border-bottom: 1px solid var(--border) !important;
font-weight: 600;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.el-table td.el-table__cell {
color: var(--text-primary) !important;
border-bottom: 1px solid var(--border) !important;
}
@@ -158,16 +243,22 @@
}
.el-table tr:hover > td {
background: #FFF0F5 !important;
background: var(--surface-2) !important;
}
.el-table__body tr.current-row > td.el-table__cell {
background: var(--border) !important;
background: var(--primary-soft) !important;
}
/* 表格行选中左侧高亮条 */
.el-table__body tr.current-row > td.el-table__cell:first-child {
border-left: 3px solid var(--primary) !important;
}
/* -------------------- 复选框 -------------------- */
.el-checkbox__inner {
border: 1px solid var(--border) !important;
background: white !important;
background: var(--surface-3) !important;
}
.el-checkbox__inner:hover {
@@ -180,61 +271,86 @@
}
.el-checkbox__input.is-disabled .el-checkbox__inner {
background: #f5f5f5 !important;
border-color: #e4e7ed !important;
background: var(--el-disabled-bg) !important;
border-color: var(--el-disabled-border) !important;
}
/* -------------------- 分页 -------------------- */
.el-pagination button {
border: 1px solid var(--border) !important;
background: var(--bg-light) !important;
background: var(--surface) !important;
color: var(--text-secondary) !important;
border-radius: var(--radius-sm) !important;
}
.el-pagination button:hover {
background: rgba(255, 107, 157, 0.1) !important;
background: var(--surface-2) !important;
border-color: var(--primary) !important;
color: var(--primary) !important;
}
.el-pagination li.is-active {
background: var(--primary) !important;
color: white !important;
border-color: var(--primary) !important;
.el-pagination button:disabled {
background: var(--surface) !important;
color: var(--text-muted) !important;
border-color: var(--border) !important;
}
.el-pager li {
background: var(--bg-light) !important;
background: var(--surface) !important;
color: var(--text-secondary) !important;
border: 1px solid var(--border) !important;
border-radius: var(--radius-sm) !important;
}
.el-pager li:hover {
color: var(--primary) !important;
border-color: var(--primary) !important;
}
.el-pager li.is-active {
background: var(--primary) !important;
color: var(--bg) !important;
border-color: var(--primary) !important;
font-weight: 600;
}
/* -------------------- 标签 -------------------- */
.el-tag {
border-radius: var(--radius-sm) !important;
font-weight: 500;
}
.el-tag--primary {
background: rgba(255, 107, 157, 0.1) !important;
background: var(--primary-soft) !important;
color: var(--primary) !important;
border-color: rgba(255, 107, 157, 0.3) !important;
border-color: rgba(146, 124, 255, 0.3) !important;
}
.el-tag--success {
background: rgba(0, 212, 255, 0.1) !important;
color: var(--cyan) !important;
border-color: rgba(0, 212, 255, 0.3) !important;
background: var(--success-soft) !important;
color: var(--success) !important;
border-color: rgba(34, 197, 94, 0.3) !important;
}
.el-tag--warning {
background: rgba(255, 184, 0, 0.1) !important;
color: var(--yellow) !important;
border-color: rgba(255, 184, 0, 0.3) !important;
background: var(--warning-soft) !important;
color: var(--warning) !important;
border-color: rgba(245, 158, 11, 0.3) !important;
}
.el-tag--danger {
background: rgba(255, 107, 107, 0.1) !important;
background: var(--danger-soft) !important;
color: var(--danger) !important;
border-color: rgba(255, 107, 107, 0.3) !important;
border-color: rgba(251, 113, 133, 0.3) !important;
}
.el-tag--info {
background: var(--info-soft) !important;
color: var(--info) !important;
border-color: rgba(56, 189, 248, 0.3) !important;
}
/* -------------------- 评分 -------------------- */
.el-rate__icon {
color: var(--border) !important;
}
@@ -243,36 +359,54 @@
color: var(--primary) !important;
}
/* -------------------- 对话框 -------------------- */
.el-dialog {
border: 1px solid var(--border) !important;
background: var(--surface) !important;
border-radius: var(--radius-lg) !important;
box-shadow: var(--shadow-xl) !important;
}
.el-dialog__header {
border-bottom: 1px solid var(--border) !important;
padding: 16px 20px;
margin: 0;
}
.el-dialog__title {
color: var(--text-primary) !important;
font-weight: 600;
}
.el-dialog__body {
background: white !important;
background: transparent !important;
color: var(--text-secondary) !important;
padding: 20px;
}
.el-dialog__footer {
border-top: 1px solid var(--border) !important;
padding: 16px 20px;
}
/* -------------------- 下拉菜单 -------------------- */
.el-dropdown-menu {
border: 1px solid var(--border) !important;
box-shadow: var(--shadow-md) !important;
box-shadow: var(--shadow-lg) !important;
background: var(--surface) !important;
border-radius: var(--radius-md) !important;
}
.el-dropdown-menu__item {
color: var(--text-primary) !important;
color: var(--text-secondary) !important;
}
.el-dropdown-menu__item:hover {
background: rgba(255, 107, 157, 0.1) !important;
background: var(--primary-soft) !important;
color: var(--primary) !important;
}
/* -------------------- 滚动条 -------------------- */
.el-scrollbar__wrap::-webkit-scrollbar {
width: 6px;
height: 6px;
@@ -287,46 +421,54 @@
background: var(--primary);
}
/* -------------------- 表单 -------------------- */
.el-form-item__label {
color: var(--text-muted) !important;
color: var(--text-secondary) !important;
font-weight: 500;
}
.el-form-item__error {
color: var(--danger) !important;
}
/* -------------------- 消息提示 -------------------- */
.el-message {
border: 1px solid var(--border) !important;
box-shadow: var(--shadow-md) !important;
box-shadow: var(--shadow-lg) !important;
background: var(--surface) !important;
border-radius: var(--radius-md) !important;
}
.el-message--success {
background: rgba(0, 212, 255, 0.1) !important;
border-color: rgba(0, 212, 255, 0.3) !important;
color: var(--cyan) !important;
background: var(--surface) !important;
border-color: var(--success) !important;
color: var(--success) !important;
}
.el-message--error {
background: rgba(255, 107, 107, 0.1) !important;
border-color: rgba(255, 107, 107, 0.3) !important;
background: var(--surface) !important;
border-color: var(--danger) !important;
color: var(--danger) !important;
}
.el-message--warning {
background: rgba(255, 184, 0, 0.1) !important;
border-color: rgba(255, 184, 0, 0.3) !important;
color: var(--yellow) !important;
background: var(--surface) !important;
border-color: var(--warning) !important;
color: var(--warning) !important;
}
.el-message--info {
background: rgba(255, 107, 157, 0.1) !important;
border-color: rgba(255, 107, 157, 0.3) !important;
background: var(--surface) !important;
border-color: var(--primary) !important;
color: var(--primary) !important;
}
/* -------------------- 消息盒子 -------------------- */
.el-message-box {
border: 1px solid var(--border) !important;
box-shadow: var(--shadow-md) !important;
box-shadow: var(--shadow-xl) !important;
background: var(--surface) !important;
border-radius: var(--radius-lg) !important;
}
.el-message-box__header {
@@ -334,33 +476,118 @@
}
.el-message-box__title {
color: var(--primary) !important;
color: var(--text-primary) !important;
font-weight: 600;
}
.el-message-box__content {
color: var(--text-primary) !important;
color: var(--text-secondary) !important;
}
.el-message-box__btns {
border-top: 1px solid var(--border) !important;
}
/* -------------------- 警告提示 -------------------- */
.el-alert {
border-radius: var(--radius-md) !important;
}
.el-alert--success {
background-color: rgba(0, 255, 136, 0.1) !important;
border-color: var(--green) !important;
background-color: var(--success-soft) !important;
border: 1px solid rgba(34, 197, 94, 0.3) !important;
color: var(--success) !important;
}
.el-alert--info {
background-color: rgba(255, 107, 157, 0.1) !important;
border-color: var(--primary) !important;
background-color: var(--primary-soft) !important;
border: 1px solid rgba(146, 124, 255, 0.3) !important;
color: var(--primary) !important;
}
.el-alert--warning {
background-color: rgba(255, 184, 0, 0.1) !important;
border-color: var(--yellow) !important;
background-color: var(--warning-soft) !important;
border: 1px solid rgba(245, 158, 11, 0.3) !important;
color: var(--warning) !important;
}
.el-alert--error {
background-color: rgba(255, 51, 102, 0.1) !important;
border-color: var(--danger) !important;
background-color: var(--danger-soft) !important;
border: 1px solid rgba(251, 113, 133, 0.3) !important;
color: var(--danger) !important;
}
/* -------------------- Switch 开关 -------------------- */
.theme-switch.el-switch .el-switch__core {
background: var(--surface-3);
border-color: var(--border);
}
.theme-switch.el-switch.is-checked .el-switch__core {
border-color: var(--primary) !important;
background-color: var(--primary) !important;
}
/* -------------------- 进度条 -------------------- */
.el-progress-bar__outer {
background-color: var(--surface-3) !important;
}
.el-progress-bar__inner {
background: var(--gradient-primary) !important;
}
.el-progress__text {
color: var(--text-secondary) !important;
}
/* -------------------- 菜单 -------------------- */
.el-menu {
background: transparent !important;
border-right: none !important;
}
.el-menu-item {
color: var(--text-secondary) !important;
border-radius: var(--radius-md);
margin: 4px 8px;
}
.el-menu-item:hover {
background: var(--surface-2) !important;
color: var(--primary) !important;
}
.el-menu-item.is-active {
background: var(--primary-soft) !important;
color: var(--primary) !important;
font-weight: 600;
}
/* -------------------- Tabs -------------------- */
.el-tabs__nav-wrap::after {
background-color: var(--border) !important;
}
.el-tabs__item {
color: var(--text-muted) !important;
}
.el-tabs__item:hover {
color: var(--primary) !important;
}
.el-tabs__item.is-active {
color: var(--primary) !important;
}
.el-tabs__active-bar {
background-color: var(--primary) !important;
}
/* -------------------- Tooltip -------------------- */
.el-tooltip__popper {
background: var(--surface-2) !important;
border: 1px solid var(--border) !important;
color: var(--text-primary) !important;
}

View File

@@ -1,15 +1,19 @@
/**
* 工具类 CSS - 冷灰紫主题
* 提供通用的布局和样式工具类
*/
/* ==================== 卡片 ==================== */
.card-base {
border-radius: var(--radius-xl);
background: var(--bg-card);
border-radius: var(--radius-lg);
background: var(--surface);
border: 1px solid var(--border);
box-shadow: var(--shadow-sm);
transition: var(--transition-hover);
}
.card-base:hover {
box-shadow: var(--shadow-md);
border-color: var(--border-light);
transform: translateY(-2px);
border-color: var(--primary);
}
.card-header {
@@ -22,14 +26,15 @@
.card-title {
font-size: 18px;
font-weight: 700;
color: var(--primary);
letter-spacing: 1px;
font-weight: 600;
color: var(--text-primary);
letter-spacing: 0.5px;
}
/* ==================== 按钮工具类 ==================== */
.btn-base {
border-radius: var(--radius-md);
font-weight: 600;
font-weight: 500;
transition: var(--transition-base);
border: 1px solid var(--border);
display: inline-flex;
@@ -38,61 +43,87 @@
gap: 8px;
cursor: pointer;
outline: none;
padding: 8px 16px;
background: var(--surface-2);
color: var(--text-secondary);
}
.btn-primary {
background: var(--gradient-primary);
.btn-base:hover {
border-color: var(--primary);
color: var(--primary);
background: var(--surface-3);
}
/* 主要按钮 - 深紫实心 */
.btn-primary {
background: var(--primary-solid);
border-color: var(--primary-solid);
color: white;
}
.btn-primary:hover {
box-shadow: 0 4px 12px rgba(255, 107, 157, 0.3);
transform: translateY(-2px);
background: var(--primary-solid-hover);
border-color: var(--primary-solid-hover);
box-shadow: var(--shadow-primary-md);
transform: translateY(-1px);
color: white;
}
/* 成功按钮 */
.btn-success {
background: var(--gradient-cyan);
border-color: var(--cyan);
color: white;
background: var(--success);
border-color: var(--success);
color: var(--bg);
}
.btn-success:hover {
box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3);
transform: translateY(-2px);
background: #2DD4BF;
border-color: #2DD4BF;
box-shadow: 0 0 20px rgba(34, 197, 94, 0.3);
transform: translateY(-1px);
color: var(--bg);
}
/* 警告按钮 */
.btn-warning {
background: var(--gradient-yellow);
border-color: var(--yellow);
color: white;
background: var(--warning);
border-color: var(--warning);
color: var(--bg);
}
.btn-warning:hover {
box-shadow: 0 4px 12px rgba(255, 184, 0, 0.3);
transform: translateY(-2px);
background: #FBBF24;
border-color: #FBBF24;
box-shadow: 0 0 20px rgba(245, 158, 11, 0.3);
transform: translateY(-1px);
color: var(--bg);
}
/* 危险按钮 */
.btn-danger {
background: var(--gradient-danger);
background: var(--danger);
border-color: var(--danger);
color: white;
}
.btn-danger:hover {
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);
transform: translateY(-2px);
background: #FCA5A5;
border-color: #FCA5A5;
box-shadow: 0 0 20px rgba(251, 113, 133, 0.3);
transform: translateY(-1px);
color: white;
}
.btn-icon {
font-size: 20px;
font-size: 18px;
margin-right: 0;
vertical-align: middle;
}
/* ==================== 布局 ==================== */
.page-container {
padding: 20px;
background: var(--bg-page);
padding: 24px;
background: var(--bg);
min-height: 100vh;
}
@@ -104,7 +135,7 @@
.form-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
gap: 12px;
align-items: flex-end;
}
@@ -114,12 +145,19 @@
gap: 20px;
}
@media (max-width: 768px) {
@media (max-width: 1200px) {
.stat-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.stat-grid {
grid-template-columns: 1fr;
}
}
/* Flex 工具类 */
.flex-center {
display: flex;
align-items: center;
@@ -137,50 +175,103 @@
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-1 {
flex: 1;
}
/* ==================== 文字颜色 ==================== */
.text-primary {
color: var(--primary);
}
.text-cyan {
color: var(--cyan);
.text-accent {
color: var(--accent);
}
.text-success {
color: var(--green);
color: var(--success);
}
.text-warning {
color: var(--yellow);
color: var(--warning);
}
.text-danger {
color: var(--danger);
}
.text-info {
color: var(--info);
}
.text-muted {
color: var(--text-muted);
}
.text-secondary {
color: var(--text-secondary);
}
/* ==================== 背景 ==================== */
.bg-gradient-primary {
background: var(--gradient-primary);
}
.bg-gradient-cyan {
background: var(--gradient-cyan);
.bg-gradient-accent {
background: var(--gradient-accent);
}
.border-pink {
.bg-surface {
background: var(--surface);
}
.bg-surface-2 {
background: var(--surface-2);
}
.bg-surface-3 {
background: var(--surface-3);
}
/* ==================== 边框 ==================== */
.border-default {
border: 1px solid var(--border);
}
.rounded-xl {
border-radius: var(--radius-xl);
.border-light {
border: 1px solid var(--border-light);
}
.border-primary {
border: 1px solid var(--primary);
}
.border-none {
border: none;
}
/* ==================== 圆角 ==================== */
.rounded-sm {
border-radius: var(--radius-sm);
}
.rounded-md {
border-radius: var(--radius-md);
}
.rounded-lg {
border-radius: var(--radius-lg);
}
.rounded-xl {
border-radius: var(--radius-xl);
}
/* ==================== 阴影 ==================== */
.shadow-sm {
box-shadow: var(--shadow-sm);
}
@@ -188,3 +279,156 @@
.shadow-md {
box-shadow: var(--shadow-md);
}
.shadow-lg {
box-shadow: var(--shadow-lg);
}
.shadow-xl {
box-shadow: var(--shadow-xl);
}
.shadow-none {
box-shadow: none;
}
.shadow-primary {
box-shadow: var(--shadow-primary-md);
}
/* ==================== 间距 ==================== */
.gap-4 {
gap: 4px;
}
.gap-8 {
gap: 8px;
}
.gap-12 {
gap: 12px;
}
.gap-16 {
gap: 16px;
}
.gap-20 {
gap: 20px;
}
/* ==================== 文本工具 ==================== */
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-nowrap {
white-space: nowrap;
}
.text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.font-medium {
font-weight: 500;
}
.font-semibold {
font-weight: 600;
}
.font-bold {
font-weight: 700;
}
/* ==================== 显示 ==================== */
.hidden {
display: none;
}
.block {
display: block;
}
.inline-block {
display: inline-block;
}
/* ==================== 响应式隐藏 ==================== */
@media (max-width: 768px) {
.hidden-mobile {
display: none !important;
}
}
@media (min-width: 769px) {
.hidden-desktop {
display: none !important;
}
}
/* ==================== 焦点样式 ==================== */
.focus-primary:focus {
outline: none;
box-shadow: var(--shadow-primary-sm);
border-color: var(--primary);
}
.focus-accent:focus {
outline: none;
box-shadow: var(--shadow-accent-sm);
border-color: var(--accent);
}
/* ==================== 状态指示器 ==================== */
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
}
.status-dot--success {
background: var(--success);
box-shadow: 0 0 8px rgba(34, 197, 94, 0.5);
}
.status-dot--warning {
background: var(--warning);
box-shadow: 0 0 8px rgba(245, 158, 11, 0.5);
}
.status-dot--danger {
background: var(--danger);
box-shadow: 0 0 8px rgba(251, 113, 133, 0.5);
}
.status-dot--info {
background: var(--info);
box-shadow: 0 0 8px rgba(56, 189, 248, 0.5);
}
/* ==================== 分隔线 ==================== */
.divider {
height: 1px;
background: var(--border);
margin: 16px 0;
}
.divider-vertical {
width: 1px;
background: var(--border);
margin: 0 16px;
align-self: stretch;
}

View File

@@ -1,43 +1,87 @@
/**
* CSS 变量定义 - 冷灰紫主题
* 设计理念:冷灰做信息底座,克制紫色做品牌识别和交互强调
* 参考Material 3 颜色角色体系
*/
:root {
--primary: #FF6B9D;
--primary-light: #FF8FB3;
--primary-dark: #FF5A8F;
--cyan: #00D4FF;
--cyan-light: #00E5FF;
--cyan-dark: #00B8E0;
--green: #34D399;
--yellow: #FFB800;
--danger: #FF6B6B;
--purple: #A855F7;
--bg-page: #FAFAFA;
--bg-card: #FFFFFF;
--bg-light: #FFF9FB;
--text-primary: #333333;
--text-secondary: #999999;
--text-muted: #666666;
--border: #FFE4EC;
--border-light: #FFD6E3;
--gradient-primary: linear-gradient(135deg, #FF6B9D 0%, #FF8FB3 100%);
--gradient-cyan: linear-gradient(135deg, #00D4FF 0%, #00E5FF 100%);
--gradient-yellow: linear-gradient(135deg, #FFB800 0%, #FFD000 100%);
--gradient-danger: linear-gradient(135deg, #FF6B6B 0%, #FF8B8B 100%);
/* ==================== 背景层次 (Surface Roles) ==================== */
--bg: #0F1117; /* 最底层背景,接近黑但不是纯黑 */
--surface: #181C25; /* 卡片、表格、侧边栏 */
--surface-2: #1F2430; /* 悬停状态、次级面板 */
--surface-3: #262C3A; /* 输入框、选中行背景 */
--border: #2E3545; /* 边框,负责把结构切出来 */
--border-light: #3A4356; /* 稍亮的边框 */
/* ==================== 文字颜色 ==================== */
--text-primary: #F5F7FA; /* 主要文字,对比度充足 */
--text-secondary: #A5AEBD; /* 次要文字 */
--text-muted: #7C8596; /* 弱化文字、placeholder */
/* ==================== 品牌紫色系 (Brand Purple) ==================== */
/* 亮紫:用于链接、选中、图标、焦点 - "发光"和识别 */
--primary: #927CFF;
--primary-rgb: 146, 124, 255;
--primary-hover: #A78BFA;
--primary-soft: #2A2442; /* 淡紫背景,用于选中态底色 */
/* 深紫:用于实心按钮,配白字更稳 - "承载文字" */
--primary-solid: #6B4EFF;
--primary-solid-hover: #5B3DF5;
/* ==================== 辅助色 (Accent) ==================== */
--accent: #2DD4BF; /* 青绿色,辅助强调 */
--accent-rgb: 45, 212, 191;
--accent-soft: #163A39; /* 淡青背景 */
/* ==================== 语义状态色 (Semantic Colors) ==================== */
/* 紫色只表示"交互和品牌";绿/橙/红只表示"系统状态" */
--success: #22C55E;
--success-rgb: 34, 197, 94;
--success-soft: #1A3A28;
--warning: #F59E0B;
--warning-rgb: 245, 158, 11;
--warning-soft: #3D3118;
--danger: #FB7185;
--danger-rgb: 251, 113, 133;
--danger-soft: #3D1F26;
--info: #38BDF8;
--info-rgb: 56, 189, 248;
--info-soft: #1A3A4A;
/* ==================== 渐变 ==================== */
--gradient-primary: linear-gradient(135deg, #6B4EFF 0%, #927CFF 100%);
--gradient-accent: linear-gradient(135deg, #2DD4BF 0%, #38BDF8 100%);
--gradient-surface: linear-gradient(180deg, #181C25 0%, #1F2430 100%);
/* ==================== 圆角 ==================== */
--radius-sm: 6px;
--radius-md: 8px;
--radius-md: 10px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-2xl: 20px;
--shadow-sm: 0 2px 8px rgba(255, 107, 157, 0.08);
--shadow-md: 0 4px 12px rgba(255, 107, 157, 0.15);
--shadow-lg: 0 8px 20px rgba(255, 107, 157, 0.2);
--transition-base: all 0.3s ease;
--transition-hover: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
--radius-xl: 14px;
--radius-2xl: 16px;
/* ==================== 阴影 (克制使用,更多靠层级和边框) ==================== */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5);
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.6);
/* 紫色光晕 - 用于焦点态 */
--shadow-primary-sm: 0 0 0 2px rgba(146, 124, 255, 0.2);
--shadow-primary-md: 0 0 20px rgba(146, 124, 255, 0.15);
--shadow-accent-sm: 0 0 0 2px rgba(45, 212, 191, 0.2);
/* ==================== 过渡 ==================== */
--transition-base: all 0.2s ease;
--transition-hover: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
/* ==================== Element Plus 专用覆盖 ==================== */
--el-disabled-bg: #262C3A;
--el-disabled-border: #3A4356;
--el-disabled-text: #7C8596;
--el-switch-inactive: #3A4356;
}