From 086301e375541ca76c5554e643a0b8e5217e8b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=A8=AA?= <2938139566@qq.com> Date: Wed, 15 Oct 2025 15:21:27 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=9B=B4=E6=96=B0UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MetaCore/ui/icon_manager.py | 14 +- MetaCore/ui/main_window.py | 20 +- MetaCore/ui/project_area.py | 159 +-- MetaCore/ui/project_card.py | 453 ++++++-- MetaCore/ui/sidebar.py | 100 +- MetaCore/ui/styles.py | 1945 +++++++---------------------------- data/projects.json | 19 +- 7 files changed, 867 insertions(+), 1843 deletions(-) diff --git a/MetaCore/ui/icon_manager.py b/MetaCore/ui/icon_manager.py index 4d811a2..194a6b2 100644 --- a/MetaCore/ui/icon_manager.py +++ b/MetaCore/ui/icon_manager.py @@ -13,7 +13,8 @@ class IconManager: """图标管理器""" # 图标目录路径 - ICONS_DIR = "Resources/Icons" + # ICONS_DIR = "Resources/Icons" + ICONS_DIR = os.path.join(os.path.dirname(__file__), "..", "Resources", "Icons") # 图标文件映射 ICON_FILES = { @@ -41,8 +42,13 @@ class IconManager: 'system_settings': 'system.png', # 树箭头 - 'down': 'down.png', - 'right': 'right.png', + 'down': 'solid_down_arrows.png', + 'right': 'solid_right_arrows.png', + + 'search': 'search_icon.png', + 'infomation': 'infomation_icon.png', + + 'project_empty_icon': 'project_empty_icon.png', } # 图标缓存 @@ -137,6 +143,8 @@ class IconManager: bool: 图标文件是否存在 """ icon_path = cls.get_icon_path(icon_name) + print("icon_path", icon_path) + print("os.path.exists(icon_path)", os.path.exists(icon_path)) return icon_path and os.path.exists(icon_path) @classmethod diff --git a/MetaCore/ui/main_window.py b/MetaCore/ui/main_window.py index c987044..ae021a9 100644 --- a/MetaCore/ui/main_window.py +++ b/MetaCore/ui/main_window.py @@ -28,11 +28,11 @@ class MainWindow(QMainWindow): self.init_ui() self.connect_signals() - # 设置窗口属性 + # 设置窗口属性 - 匹配 Figma 设计规范 self.setWindowTitle("MetaCore - 项目管理平台") self.setWindowIcon(IconManager.get_icon('app')) - self.setMinimumSize(1000, 700) - self.resize(1400, 900) + self.setMinimumSize(1200, 800) # 增加最小尺寸,确保良好的用户体验 + self.resize(1440, 960) # 调整默认尺寸,匹配现代显示器比例 # 响应式布局标志 self.is_compact_mode = False @@ -201,22 +201,22 @@ class MainWindow(QMainWindow): """窗口大小变化事件""" super().resizeEvent(event) - # 检查是否需要切换到紧凑模式 + # 检查是否需要切换到紧凑模式 - 匹配 Figma 响应式断点 width = event.size().width() - should_be_compact = width < 1200 + should_be_compact = width < 1400 # 调整断点,匹配现代设计标准 if should_be_compact != self.is_compact_mode: self.is_compact_mode = should_be_compact self.update_layout_mode() def update_layout_mode(self): - """更新布局模式""" + """更新布局模式 - 匹配 Figma 响应式设计""" if self.is_compact_mode: - # 紧凑模式:缩小侧边栏 - self.sidebar.setFixedWidth(240) + # 紧凑模式:缩小侧边栏,匹配小屏幕设计 + self.sidebar.setFixedWidth(260) else: - # 正常模式:标准侧边栏宽度 - self.sidebar.setFixedWidth(280) + # 正常模式:标准侧边栏宽度,匹配 Figma 设计 + self.sidebar.setFixedWidth(300) def on_filter_changed(self, filter_type: str): """过滤器改变""" diff --git a/MetaCore/ui/project_area.py b/MetaCore/ui/project_area.py index 62341c9..7811e1b 100644 --- a/MetaCore/ui/project_area.py +++ b/MetaCore/ui/project_area.py @@ -23,9 +23,13 @@ class ProjectArea(QWidget): def __init__(self, project_manager: ProjectManager): super().__init__() + self.setObjectName("projectArea") + self.setAttribute(Qt.WA_StyledBackground, True) self.project_manager = project_manager self.view_mode = "grid" # grid 或 list self.projects = [] + self.grid_view_btn = None + self.list_view_btn = None self.init_ui() self.connect_signals() @@ -36,34 +40,40 @@ class ProjectArea(QWidget): def init_ui(self): """初始化UI""" layout = QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) + layout.setContentsMargins(0, 30, 24, 30) layout.setSpacing(0) + + # 主内容容器,方便区分背景颜色 + self.content_widget = QWidget() + self.content_widget.setObjectName("projectAreaContent") + self.content_layout = QVBoxLayout(self.content_widget) + self.content_layout.setContentsMargins(0, 0, 0, 0) + self.content_layout.setSpacing(0) + + layout.addWidget(self.content_widget) # 顶部工具栏 - self.create_toolbar(layout) - - # 搜索和过滤区域 - self.create_search_filter_area(layout) + self.create_toolbar(self.content_layout) # 项目显示区域 - self.create_project_display_area(layout) + self.create_project_display_area(self.content_layout) def create_toolbar(self, layout): - """创建顶部工具栏""" - toolbar_widget = QWidget() - toolbar_widget.setObjectName("toolbar") - toolbar_layout = QHBoxLayout(toolbar_widget) - toolbar_layout.setContentsMargins(30, 20, 30, 10) - - # 面包屑导航容器 + """创建顶部工具区域""" + header_widget = QWidget() + header_widget.setObjectName("contentHeader") + header_layout = QHBoxLayout(header_widget) + header_layout.setContentsMargins(36, 26, 36, 28) + header_layout.setSpacing(16) + breadcrumb_container = QWidget() breadcrumb_container.setObjectName("breadcrumbContainer") breadcrumb_layout = QHBoxLayout(breadcrumb_container) breadcrumb_layout.setContentsMargins(0, 0, 0, 0) - breadcrumb_layout.setSpacing(0) + breadcrumb_layout.setSpacing(8) self.home_label = QLabel("我的项目") - self.home_label.setObjectName("breadcrumbItem") + self.home_label.setObjectName("breadcrumbBase") breadcrumb_layout.addWidget(self.home_label) self.separator_label = QLabel("/") @@ -74,106 +84,27 @@ class ProjectArea(QWidget): self.current_label.setObjectName("breadcrumbCurrent") breadcrumb_layout.addWidget(self.current_label) - breadcrumb_layout.addStretch() - - toolbar_layout.addWidget(breadcrumb_container) - - # 右侧操作按钮 - actions_layout = QHBoxLayout() - - # 导入项目按钮 - self.import_project_btn = QPushButton("导入项目") - if IconManager.icon_exists('import'): - self.import_project_btn.setIcon(IconManager.get_icon('import')) - else: - self.import_project_btn = QPushButton("↑ 导入项目") - self.import_project_btn.setObjectName("importBtn") - self.import_project_btn.clicked.connect(self.import_project_requested.emit) - actions_layout.addWidget(self.import_project_btn) - - # 创建项目按钮 - self.create_project_btn = QPushButton("创建") - if IconManager.icon_exists('create'): - self.create_project_btn.setIcon(IconManager.get_icon('create')) - else: - self.create_project_btn = QPushButton("+ 创建") - self.create_project_btn.setObjectName("primaryBtn") - self.create_project_btn.clicked.connect(self.create_project_requested.emit) - actions_layout.addWidget(self.create_project_btn) - - toolbar_layout.addLayout(actions_layout) - layout.addWidget(toolbar_widget) - - def create_search_filter_area(self, layout): - """创建搜索和过滤区域""" - # 内容头部 - 调整高度更紧凑 - content_header = QWidget() - content_header.setObjectName("contentHeader") - header_layout = QHBoxLayout(content_header) - header_layout.setContentsMargins(30, 12, 30, 12) # 减少上下边距:20->12 - - # 标题 - self.title_label = QLabel("项目概述") - self.title_label.setObjectName("contentTitle") - header_layout.addWidget(self.title_label) - + header_layout.addWidget(breadcrumb_container) header_layout.addStretch() - # 搜索输入框 self.search_input = QLineEdit() self.search_input.setObjectName("searchInput") self.search_input.setPlaceholderText("搜索项目...") + self.search_input.setClearButtonEnabled(True) + if IconManager.icon_exists('search'): + search_action = self.search_input.addAction(IconManager.get_icon('search', QSize(30, 30)), QLineEdit.TrailingPosition) + self.search_input.setFixedWidth(508) self.search_input.textChanged.connect(self.search_changed.emit) - self.search_input.setMaximumWidth(250) # 限制最大宽度 - header_layout.addWidget(self.search_input) + header_layout.addWidget(self.search_input, 0, Qt.AlignRight) - # 视图控制按钮 - view_controls = QHBoxLayout() - - # 网格视图按钮 - self.grid_view_btn = QPushButton() - if IconManager.icon_exists('grid_view'): - self.grid_view_btn.setIcon(IconManager.get_icon('grid_view', QSize(16, 16))) - self.grid_view_btn.setIconSize(QSize(16, 16)) - else: - self.grid_view_btn.setText("⊞") - self.grid_view_btn.setObjectName("viewBtn") - self.grid_view_btn.setCheckable(True) - self.grid_view_btn.setChecked(True) - self.grid_view_btn.setToolTip("网格视图") - self.grid_view_btn.clicked.connect(lambda: self.set_view_mode("grid")) - view_controls.addWidget(self.grid_view_btn) + layout.addWidget(header_widget) - # 列表视图按钮 - self.list_view_btn = QPushButton() - if IconManager.icon_exists('list_view'): - self.list_view_btn.setIcon(IconManager.get_icon('list_view', QSize(16, 16))) - self.list_view_btn.setIconSize(QSize(16, 16)) - else: - self.list_view_btn.setText("☰") - self.list_view_btn.setObjectName("viewBtn") - self.list_view_btn.setCheckable(True) - self.list_view_btn.setToolTip("列表视图") - self.list_view_btn.clicked.connect(lambda: self.set_view_mode("list")) - view_controls.addWidget(self.list_view_btn) - - # # 过滤按钮 - # filter_btn = QPushButton("▼") - # filter_btn.setObjectName("viewBtn") - # filter_btn.setToolTip("过滤选项") - # view_controls.addWidget(filter_btn) - - - - header_layout.addLayout(view_controls) - layout.addWidget(content_header) - - - def create_project_display_area(self, layout): """创建项目显示区域""" # 滚动区域 self.scroll_area = QScrollArea() + self.scroll_area.setObjectName("projectScrollArea") + self.scroll_area.setFrameShape(QFrame.NoFrame) self.scroll_area.setWidgetResizable(True) self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) @@ -184,8 +115,8 @@ class ProjectArea(QWidget): # 网格布局 self.projects_layout = QGridLayout(self.projects_container) - self.projects_layout.setContentsMargins(30, 20, 30, 30) - self.projects_layout.setSpacing(20) + self.projects_layout.setContentsMargins(36, 18, 6, 18) + self.projects_layout.setSpacing(24) self.projects_layout.setAlignment(Qt.AlignTop) # 设置顶部对齐 # 响应式列数 @@ -211,10 +142,8 @@ class ProjectArea(QWidget): """更新导航显示""" # 更新面包屑导航 self.home_label.setText(section) - self.current_label.setText(item_name) - # 更新主标题 - # 根据不同的导航项设置不同的标题 + # 根据不同的导航项设置显示标题 title_mapping = { "项目概述": "项目概述", "项目管理": "项目管理", @@ -224,7 +153,7 @@ class ProjectArea(QWidget): } display_title = title_mapping.get(item_name, item_name) - self.title_label.setText(display_title) + self.current_label.setText(display_title) def refresh_project_display(self): """刷新项目显示""" @@ -290,8 +219,10 @@ class ProjectArea(QWidget): self.view_mode = mode # 更新按钮状态 - self.grid_view_btn.setChecked(mode == "grid") - self.list_view_btn.setChecked(mode == "list") + if self.grid_view_btn: + self.grid_view_btn.setChecked(mode == "grid") + if self.list_view_btn: + self.list_view_btn.setChecked(mode == "list") # 刷新显示 self.refresh_project_display() @@ -348,9 +279,9 @@ class ProjectArea(QWidget): if available_width <= 0: available_width = width - 20 # 使用更小的边距 - # 固定卡片宽度和间距 - card_width = 280 # 固定卡片宽度 - spacing = 20 # 卡片间距 + # 固定卡片宽度和间距 - 匹配 Figma 设计 + card_width = 280 # 固定卡片宽度,匹配当前卡片尺寸 + spacing = 24 # 卡片间距,匹配更新后的间距 # 计算能容纳的列数 if available_width < card_width: diff --git a/MetaCore/ui/project_card.py b/MetaCore/ui/project_card.py index de6671c..f23700d 100644 --- a/MetaCore/ui/project_card.py +++ b/MetaCore/ui/project_card.py @@ -41,7 +41,7 @@ class ImageDisplayWidget(QWidget): import math target_rect = self.rect() - radius = 12.0 + radius = 5.0 # “过缩放”逻辑保持不变,我们仍然需要一张比控件大的图片 overscale_factor = 1.05 @@ -76,23 +76,26 @@ class ImageDisplayWidget(QWidget): class ProjectCard(QWidget): """项目卡片组件""" + CORNER_RADIUS = 5 + def __init__(self, project: Project, project_manager: ProjectManager, view_mode: str = "grid"): super().__init__() self.project = project self.project_manager = project_manager self.view_mode = view_mode self.project_settings_page = ProjectSettingsPage() + self.project_size_text = self._compute_project_size_text() # 设置卡片对象名称和属性 self.setObjectName("projectCard") self.setProperty("status", project.status) self.setAttribute(Qt.WA_StyledBackground) # 关键:启用样式背景继承 - # 设置尺寸和策略 + # 设置尺寸和策略 - 匹配 Figma 设计规范 if view_mode == "grid": - self.setFixedSize(280, 240) + self.setFixedSize(276, 191) else: - self.setFixedHeight(80) + self.setFixedHeight(88) # 调整列表视图高度 self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.init_ui() @@ -100,6 +103,7 @@ class ProjectCard(QWidget): # 确保样式正确应用 self.update_style() + self.apply_corner_mask() def update_style(self): """强制刷新样式""" @@ -107,6 +111,86 @@ class ProjectCard(QWidget): self.style().polish(self) self.update() + def apply_corner_mask(self): + """为整个卡片应用统一的圆角裁剪""" + rect = self.rect() + if rect.isNull(): + return + + path = QPainterPath() + path.addRoundedRect(QRectF(rect), self.CORNER_RADIUS, self.CORNER_RADIUS) + fill_polygon = path.toFillPolygon() + if fill_polygon.isEmpty(): + return + + self.setMask(QRegion(fill_polygon.toPolygon())) + + def _compute_project_size_text(self): + """根据项目路径计算大小文本""" + path = self._resolve_project_path() + if not path: + return "N/A" + try: + if not path.exists(): + return "N/A" + except OSError: + return "N/A" + size_bytes = self._calculate_path_size(path) + return self._format_size(size_bytes) + def _resolve_project_path(self): + project_path = self.project.project_dir if self.project.project_dir else self.project.path + if not project_path: + return None + if isinstance(project_path, Path): + candidate = project_path + else: + candidate = Path(str(project_path)) + if candidate == Path(): + return None + try: + return candidate if candidate.is_absolute() else candidate.resolve() + except OSError: + return candidate + @staticmethod + def _calculate_path_size(path: Path) -> int: + try: + if path.is_file(): + return path.stat().st_size + except OSError: + return 0 + total = 0 + stack = [path] + while stack: + current = stack.pop() + try: + with os.scandir(current) as entries: + for entry in entries: + try: + if entry.is_symlink(): + continue + if entry.is_file(follow_symlinks=False): + total += entry.stat(follow_symlinks=False).st_size + elif entry.is_dir(follow_symlinks=False): + stack.append(Path(entry.path)) + except OSError: + continue + except OSError: + continue + return total + @staticmethod + def _format_size(size_bytes: int) -> str: + if size_bytes <= 0: + return "0B" + units = ["B", "KB", "MB", "GB", "TB"] + size = float(size_bytes) + for unit in units: + if size < 1024 or unit == units[-1]: + if unit == "B": + return f"{int(size)}{unit}" + return f"{size:.2f}{unit}" + size /= 1024 + return f"{int(size_bytes)}B" + def init_ui(self): """初始化UI""" if self.view_mode == "grid": @@ -114,20 +198,28 @@ class ProjectCard(QWidget): else: self.create_list_layout() + def resizeEvent(self, event): + super().resizeEvent(event) + self.apply_corner_mask() + def create_grid_layout(self): - """创建网格布局""" - layout = QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - - # 项目头部 - self.create_project_header(layout) - - # 项目图片 - self.create_project_image(layout) - - # 项目底部 - self.create_project_footer(layout) + """创建网格布局 - 根据Figma设计优化""" + # 使用绝对定位的方式来实现图片背景和覆盖层效果 + self.setStyleSheet(""" + QWidget#projectCard { + border-radius: 5px; + overflow: hidden; + } + """) + + # 创建背景图片层 + self.create_background_image() + + # 创建右上角按钮 + self.create_overlay_button() + + # 创建底部信息覆盖层 + self.create_bottom_overlay() def create_list_layout(self): """创建列表布局""" @@ -162,19 +254,122 @@ class ProjectCard(QWidget): # 菜单按钮 self.create_menu_button(layout) + def create_background_image(self): + """创建背景图片层""" + # 背景图片标签,填充整个卡片 + self.background_label = QLabel(self) + self.background_label.setGeometry(0, 0, 276, 191) + self.background_label.setScaledContents(True) + self.background_label.setAlignment(Qt.AlignCenter) + + # 检查是否有项目图片 + if hasattr(self.project, 'image') and self.project.image and os.path.exists(self.project.image): + pixmap = QPixmap(self.project.image) + if not pixmap.isNull(): + # 缩放图片以填充整个区域,保持宽高比 + scaled_pixmap = pixmap.scaled(276, 191, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) + self.background_label.setPixmap(scaled_pixmap) + else: + self.set_default_background() + else: + self.set_default_background() + + def set_default_background(self): + """设置默认背景""" + # 使用project_empty_icon作为默认背景 + if IconManager.icon_exists('project_empty_icon'): + empty_pixmap = IconManager.get_pixmap('project_empty_icon', QSize(276, 191)) + if not empty_pixmap.isNull(): + self.background_label.setPixmap(empty_pixmap) + return + + # 如果图标不存在,创建一个默认的灰色背景 + default_pixmap = QPixmap(276, 191) + default_pixmap.fill(QColor(66, 67, 71)) # #424347 - Figma中的颜色 + + # 在中心绘制文件夹图标 + painter = QPainter(default_pixmap) + painter.setRenderHint(QPainter.Antialiasing) + + # 绘制文件夹图标 + font = QFont("Segoe UI Emoji", 48) + painter.setFont(font) + painter.setPen(QColor(212, 212, 212)) # #d4d4d4 + painter.drawText(default_pixmap.rect(), Qt.AlignCenter, "📁") + + painter.end() + self.background_label.setPixmap(default_pixmap) + + def create_overlay_button(self): + """创建右上角覆盖按钮""" + # 根据项目状态显示不同的按钮 + if self.project.status == 'pending_delete': + self.overlay_btn = QPushButton("✕", self) + self.overlay_btn.setObjectName("overlayDeleteBtn") + self.overlay_btn.clicked.connect(self.confirm_delete_project) + self.overlay_btn.setToolTip("确认删除项目") + else: + self.overlay_btn = QPushButton(self) + if IconManager.icon_exists('infomation'): + self.overlay_btn.setIcon(IconManager.get_icon('infomation', QSize(16, 16))) + self.overlay_btn.setIconSize(QSize(16, 16)) + else: + self.overlay_btn.setText("ⓘ") + self.overlay_btn.setObjectName("overlayInfoBtn") + self.overlay_btn.clicked.connect(self.show_context_menu) + # self.overlay_btn.setToolTip("项目信息") + + # 设置按钮位置和大小 + self.overlay_btn.setGeometry(248, 8, 20, 20) + + def create_bottom_overlay(self): + """创建底部信息覆盖层""" + # 底部覆盖层容器 + self.bottom_overlay = QWidget(self) + self.bottom_overlay.setObjectName("bottomOverlay") + self.bottom_overlay.setGeometry(0, 138, 276, 53) + + # 底部布局 + overlay_layout = QHBoxLayout(self.bottom_overlay) + overlay_layout.setContentsMargins(20, 8, 20, 8) + overlay_layout.setSpacing(8) + + # 项目标题 + title_label = QLabel(self.project.title) + title_label.setObjectName("overlayProjectTitle") + overlay_layout.addWidget(title_label) + + overlay_layout.addStretch() + + # 右侧信息区域 + info_layout = QVBoxLayout() + info_layout.setSpacing(2) + info_layout.setContentsMargins(0, 0, 0, 0) + + # 项目日期 + date_label = QLabel(self.project.date) + date_label.setObjectName("overlayProjectDate") + date_label.setAlignment(Qt.AlignRight) + info_layout.addWidget(date_label) + + # 项目大小 + # size_label = QLabel("52.00KB") # 这里可以根据实际项目大小动态设置 + size_label = QLabel(self.project_size_text) + size_label.setObjectName("overlayProjectSize") + size_label.setAlignment(Qt.AlignRight) + info_layout.addWidget(size_label) + + overlay_layout.addLayout(info_layout) + def create_project_header(self, layout): """创建项目头部""" header_widget = QWidget() header_widget.setObjectName("projectHeader") header_layout = QHBoxLayout(header_widget) - header_layout.setContentsMargins(16, 16, 16, 8) + header_layout.setContentsMargins(8, 8, 8, 8) header_layout.setSpacing(8) - - # 项目标题 - title_label = QLabel(self.project.title) - title_label.setObjectName("projectTitle") - title_label.setWordWrap(True) - header_layout.addWidget(title_label, 1) # 添加拉伸因子 + + header_layout.addStretch() # 右侧操作区 actions_layout = QHBoxLayout() @@ -184,15 +379,20 @@ class ProjectCard(QWidget): if self.project.status == 'pending_delete': self.menu_btn = QPushButton("✕") self.menu_btn.setObjectName("deleteBtn") - self.menu_btn.setFixedSize(24, 24) + self.menu_btn.setFixedSize(20, 20) self.menu_btn.clicked.connect(self.confirm_delete_project) self.menu_btn.setToolTip("确认删除项目") else: - self.menu_btn = QPushButton("⋯") + self.menu_btn = QPushButton() + if IconManager.icon_exists('infomation'): + self.menu_btn.setIcon(IconManager.get_icon('infomation', QSize(20, 20))) + self.menu_btn.setIconSize(QSize(20, 20)) + else: + self.menu_btn.setText("ⓘ") self.menu_btn.setObjectName("menuBtn") - self.menu_btn.setFixedSize(24, 24) + self.menu_btn.setFixedSize(20, 20) self.menu_btn.clicked.connect(self.show_context_menu) - self.menu_btn.setToolTip("项目操作菜单") + self.menu_btn.setToolTip("项目信息") actions_layout.addWidget(self.menu_btn) header_layout.addLayout(actions_layout) @@ -251,14 +451,36 @@ class ProjectCard(QWidget): """创建项目底部""" footer_widget = QWidget() footer_widget.setObjectName("projectFooter") - footer_layout = QVBoxLayout(footer_widget) - footer_layout.setContentsMargins(16, 0, 16, 16) # 减少顶部边距 + footer_layout = QHBoxLayout(footer_widget) + footer_layout.setContentsMargins(20, 0, 20, 0) + footer_layout.setSpacing(0) + # 项目标题(左侧) + title_label = QLabel(self.project.title) + title_label.setObjectName("projectTitle") + footer_layout.addWidget(title_label) + + footer_layout.addStretch() + + # 项目信息(右侧) + info_layout = QVBoxLayout() + info_layout.setSpacing(0) + info_layout.setContentsMargins(0, 0, 0, 0) + # 项目日期 date_label = QLabel(self.project.date) date_label.setObjectName("projectDate") - date_label.setAlignment(Qt.AlignCenter) - footer_layout.addWidget(date_label) + date_label.setAlignment(Qt.AlignRight) + info_layout.addWidget(date_label) + + # 项目大小 + # size_label = QLabel("52.00KB") # 这里可以根据实际项目大小动态设置 + size_label = QLabel(self.project_size_text) + size_label.setObjectName("projectDate") + size_label.setAlignment(Qt.AlignRight) + info_layout.addWidget(size_label) + + footer_layout.addLayout(info_layout) layout.addWidget(footer_widget) @@ -362,7 +584,14 @@ class ProjectCard(QWidget): delete_action.triggered.connect(self.delete_project) # 显示菜单 - menu.exec_(self.menu_btn.mapToGlobal(self.menu_btn.rect().bottomLeft())) + # 根据视图模式选择正确的按钮来定位菜单 + if self.view_mode == "grid" and hasattr(self, 'overlay_btn'): + menu.exec_(self.overlay_btn.mapToGlobal(self.overlay_btn.rect().bottomLeft())) + elif hasattr(self, 'menu_btn'): + menu.exec_(self.menu_btn.mapToGlobal(self.menu_btn.rect().bottomLeft())) + else: + # 如果没有按钮,使用鼠标位置 + menu.exec_(QCursor.pos()) def open_project(self): """打开项目""" @@ -569,6 +798,7 @@ class ProjectCard(QWidget): if child: child.setParent(None) + self.project_size_text = self._compute_project_size_text() self.init_ui() # 强制刷新样式 @@ -599,14 +829,24 @@ class ProjectCard(QWidget): def mousePressEvent(self, event): """鼠标点击事件""" if event.button() == Qt.LeftButton: - # 检查是否点击了菜单按钮 - if not self.menu_btn.geometry().contains(event.pos()): - if self.project.status == 'pending_delete': - # 待删除状态的项目,尝试恢复 - self.try_restore_project() - else: - # 正常状态的项目,打开项目 - self.open_project() + # 检查是否点击了覆盖按钮(新的网格布局)或菜单按钮(列表布局) + if self.view_mode == "grid": + if hasattr(self, 'overlay_btn') and not self.overlay_btn.geometry().contains(event.pos()): + if self.project.status == 'pending_delete': + # 待删除状态的项目,尝试恢复 + self.try_restore_project() + else: + # 正常状态的项目,打开项目 + self.open_project() + else: + # 列表视图的原有逻辑 + if hasattr(self, 'menu_btn') and not self.menu_btn.geometry().contains(event.pos()): + if self.project.status == 'pending_delete': + # 待删除状态的项目,尝试恢复 + self.try_restore_project() + else: + # 正常状态的项目,打开项目 + self.open_project() super().mousePressEvent(event) def try_restore_project(self): @@ -639,20 +879,37 @@ class ProjectCard(QWidget): def show_success_tooltip(self, message): """显示成功提示工具提示""" - # 临时改变菜单按钮的工具提示来显示成功状态 - original_tooltip = self.menu_btn.toolTip() + # 根据视图模式选择正确的按钮 + target_btn = None + if self.view_mode == "grid" and hasattr(self, 'overlay_btn'): + target_btn = self.overlay_btn + elif hasattr(self, 'menu_btn'): + target_btn = self.menu_btn - self.menu_btn.setToolTip(f"✅ {message}") - - # 使用定时器恢复原状态 - QTimer.singleShot(3000, lambda: self.restore_button_state(original_tooltip)) + if target_btn: + # 临时改变按钮的工具提示来显示成功状态 + original_tooltip = target_btn.toolTip() + target_btn.setToolTip(f"✅ {message}") + + # 使用定时器恢复原状态 + QTimer.singleShot(3000, lambda: self.restore_button_state(target_btn, original_tooltip)) - def restore_button_state(self, original_tooltip): + def restore_button_state(self, button, original_tooltip): """恢复按钮原始状态""" - self.menu_btn.setToolTip(original_tooltip) + if button: + button.setToolTip(original_tooltip) def refresh_preview_image(self): """刷新预览图""" + # 确定要操作的按钮 + target_btn = None + if self.view_mode == "grid" and hasattr(self, 'overlay_btn'): + target_btn = self.overlay_btn + elif hasattr(self, 'menu_btn'): + target_btn = self.menu_btn + + original_tooltip = "" + try: # 获取项目路径 project_path = self.project.project_dir if self.project.project_dir else self.project.path @@ -661,9 +918,10 @@ class ProjectCard(QWidget): return # 显示进度提示 - original_tooltip = self.menu_btn.toolTip() - self.menu_btn.setEnabled(False) - self.menu_btn.setToolTip("⏳ 正在生成预览图...") + if target_btn: + original_tooltip = target_btn.toolTip() + target_btn.setEnabled(False) + target_btn.setToolTip("⏳ 正在生成预览图...") QApplication.processEvents() # 生成新的预览图 @@ -693,18 +951,33 @@ class ProjectCard(QWidget): except Exception: pass # 忽略删除失败 else: + # 生成预览图失败,使用project_empty_icon作为默认图片 + self.project.image = None + self.project_manager.update_project(self.project) + + # 刷新显示以显示默认图标 + self.refresh_image_display() + QMessageBox.warning(self, "生成失败", - "无法生成预览图。\n\n可能原因:\n" + "无法生成预览图,已使用默认图标。\n\n可能原因:\n" "• 项目目录中没有图片文件\n" "• 图片文件格式不支持\n" "• 权限不足") except Exception as e: - QMessageBox.critical(self, "错误", f"刷新预览图时发生错误:\n{str(e)}") + # 发生异常时也使用project_empty_icon作为默认图片 + self.project.image = None + self.project_manager.update_project(self.project) + + # 刷新显示以显示默认图标 + self.refresh_image_display() + + QMessageBox.critical(self, "错误", f"刷新预览图时发生错误,已使用默认图标:\n{str(e)}") finally: # 恢复按钮状态 - self.menu_btn.setEnabled(True) - self.menu_btn.setToolTip(original_tooltip) + if target_btn: + target_btn.setEnabled(True) + target_btn.setToolTip(original_tooltip) def generate_project_preview(self, project_path): """生成项目预览图""" @@ -792,13 +1065,29 @@ class ProjectCard(QWidget): return self.create_default_preview(project_path) def create_default_preview(self, project_path): - """创建默认预览图""" + """创建默认预览图 - 使用project_empty_icon""" try: - # 创建预览图存储目录 + # 首先尝试使用project_empty_icon + if IconManager.icon_exists('project_empty_icon'): + # 创建预览图存储目录 + preview_dir = Path.cwd() / 'MetaCore' / 'Resources' / 'ProjectPreviews' + preview_dir.mkdir(parents=True, exist_ok=True) + + # 生成默认预览图文件名 + preview_filename = f"default_preview_{self.project.id}.png" + preview_path = preview_dir / preview_filename + + # 获取project_empty_icon并缩放到预览尺寸 + empty_icon = IconManager.get_pixmap('project_empty_icon', QSize(400, 300)) + if not empty_icon.isNull(): + # 保存预览图 + if empty_icon.save(str(preview_path), 'PNG'): + return str(preview_path) + + # 如果project_empty_icon不存在,创建带项目信息的默认预览图 preview_dir = Path.cwd() / 'MetaCore' / 'Resources' / 'ProjectPreviews' preview_dir.mkdir(parents=True, exist_ok=True) - # 生成默认预览图文件名 preview_filename = f"default_preview_{self.project.id}.png" preview_path = preview_dir / preview_filename @@ -861,34 +1150,21 @@ class ProjectCard(QWidget): def update_grid_image_display(self): """更新网格视图中的图片显示""" - # 找到图片容器 - for i in range(self.layout().count()): - widget = self.layout().itemAt(i).widget() - if widget and widget.objectName() == "projectImageContainer": - # 找到内部的堆叠布局 - for j in range(widget.layout().count()): - image_widget = widget.layout().itemAt(j).widget() - if image_widget and image_widget.objectName() == "projectImage": - stacked_layout = image_widget.layout() - if isinstance(stacked_layout, QStackedLayout): - # 获取图片显示控件 - image_display = stacked_layout.widget(0) - if isinstance(image_display, ImageDisplayWidget): - # 检查是否有新的图片文件 - if (hasattr(self.project, 'image') and - self.project.image and - os.path.exists(self.project.image) and - os.path.isfile(self.project.image)): - # 重新加载图片 - pixmap = QPixmap(self.project.image) - if not pixmap.isNull(): - image_display.setPixmap(pixmap) - stacked_layout.setCurrentIndex(0) - else: - stacked_layout.setCurrentIndex(1) - else: - stacked_layout.setCurrentIndex(1) - break + if self.view_mode == "grid" and hasattr(self, 'background_label'): + # 检查是否有新的图片文件 + if (hasattr(self.project, 'image') and + self.project.image and + os.path.exists(self.project.image) and + os.path.isfile(self.project.image)): + # 重新加载图片 + pixmap = QPixmap(self.project.image) + if not pixmap.isNull(): + scaled_pixmap = pixmap.scaled(276, 191, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) + self.background_label.setPixmap(scaled_pixmap) + else: + self.set_default_background() + else: + self.set_default_background() def update_list_image_display(self): """更新列表视图中的图片显示""" @@ -945,7 +1221,7 @@ class ListImageDisplayWidget(QWidget): import math target_rect = self.rect() - radius = 8.0 # 列表视图使用较小的圆角 + radius = 5.0 # 统一使用5px圆角 # 过缩放因子 overscale_factor = 1.05 @@ -971,4 +1247,3 @@ class ListImageDisplayWidget(QWidget): # 绘制图片 painter.drawPixmap(int(draw_x), int(draw_y), scaled_pixmap) - diff --git a/MetaCore/ui/sidebar.py b/MetaCore/ui/sidebar.py index f25eb58..719dde8 100644 --- a/MetaCore/ui/sidebar.py +++ b/MetaCore/ui/sidebar.py @@ -24,6 +24,8 @@ class Sidebar(QWidget): super().__init__() self.project_manager = project_manager self.current_filter = "overview" + self.setObjectName("sidebar") + self.setAttribute(Qt.WA_StyledBackground, True) # 导航项映射:filter_type -> (section, item_name) self.nav_mapping = { @@ -38,8 +40,8 @@ class Sidebar(QWidget): self.init_ui() self.connect_signals() - # 设置固定宽度 - self.setFixedWidth(280) + # 设置固定宽度 - 匹配 Figma 设计规范 + self.setFixedWidth(313) def init_ui(self): """初始化UI""" @@ -65,23 +67,26 @@ class Sidebar(QWidget): logo_widget = QWidget() logo_widget.setObjectName("logoWidget") logo_layout = QHBoxLayout(logo_widget) - logo_layout.setContentsMargins(20, 20, 20, 20) - - # Logo图标 - 使用更专业的图标 - logo_icon = QLabel() - if IconManager.icon_exists('logo'): - logo_icon.setPixmap(IconManager.get_pixmap('logo', QSize(24, 24))) - else: - logo_icon.setText("⬛") # 备选文字图标 - logo_icon.setObjectName("logoIcon") - logo_layout.addWidget(logo_icon) + logo_layout.setContentsMargins(37, 32, 46, 24) + logo_layout.setSpacing(28) + logo_layout.setAlignment(Qt.AlignCenter) + + logo_icon = QLabel() + logo_icon.setObjectName("logoIcon") + logo_icon.setAlignment(Qt.AlignCenter) + logo_icon.setFixedSize(80, 80) + logo_icon.setScaledContents(True) + if IconManager.icon_exists('logo'): + logo_icon.setPixmap(IconManager.get_pixmap('logo', QSize(80, 80))) + else: + logo_icon.setText("") + logo_layout.addWidget(logo_icon, alignment=Qt.AlignCenter) - # Logo文字 logo_text = QLabel("MetaCore") logo_text.setObjectName("logoText") - logo_layout.addWidget(logo_text) - - logo_layout.addStretch() + logo_text.setAlignment(Qt.AlignCenter) + logo_layout.addWidget(logo_text, 0, Qt.AlignBottom) + layout.addWidget(logo_widget) def create_quick_actions(self, layout): @@ -89,31 +94,33 @@ class Sidebar(QWidget): actions_widget = QWidget() actions_widget.setObjectName("quickActions") actions_layout = QVBoxLayout(actions_widget) - actions_layout.setContentsMargins(20, 10, 20, 20) - actions_layout.setSpacing(10) + actions_layout.setContentsMargins(37, 24, 46, 24) + actions_layout.setSpacing(12) - # 创建新项目按钮 - self.create_btn = QPushButton("创建新项目") - if IconManager.icon_exists('create'): - self.create_btn.setIcon(IconManager.get_icon('create')) - else: - self.create_btn = QPushButton("+ 创建新项目") + self.create_btn = QPushButton("新建项目") + # if IconManager.icon_exists('create'): + # self.create_btn.setIcon(IconManager.get_icon('create')) + # self.create_btn.setIconSize(QSize(18, 18)) self.create_btn.setObjectName("createBtn") + self.create_btn.setCursor(Qt.PointingHandCursor) + self.create_btn.setMinimumHeight(36) + self.create_btn.setMaximumHeight(36) self.create_btn.clicked.connect(self.create_project_requested.emit) actions_layout.addWidget(self.create_btn) - # 导入项目按钮 self.import_btn = QPushButton("导入项目") - if IconManager.icon_exists('import'): - self.import_btn.setIcon(IconManager.get_icon('import')) - else: - self.import_btn = QPushButton("↑ 导入项目") + # if IconManager.icon_exists('import'): + # self.import_btn.setIcon(IconManager.get_icon('import')) + # self.import_btn.setIconSize(QSize(18, 18)) self.import_btn.setObjectName("sidebarImportBtn") + self.import_btn.setCursor(Qt.PointingHandCursor) + self.import_btn.setMinimumHeight(36) + self.import_btn.setMaximumHeight(36) self.import_btn.clicked.connect(self.import_project_requested.emit) actions_layout.addWidget(self.import_btn) layout.addWidget(actions_widget) - + def create_navigation_menu(self, layout): """创建导航菜单""" # 滚动区域 @@ -127,8 +134,8 @@ class Sidebar(QWidget): nav_widget = QWidget() nav_widget.setObjectName("navWidget") nav_layout = QVBoxLayout(nav_widget) - nav_layout.setContentsMargins(0, 0, 0, 0) # 边距 - nav_layout.setSpacing(0) # 间距 + nav_layout.setContentsMargins(0, 10, 0, 0) # 边距:上10px + nav_layout.setSpacing(10) # 分组间距:10px # 我的项目分组 self.create_nav_section(nav_layout, "我的项目", [ @@ -162,11 +169,11 @@ class Sidebar(QWidget): section_layout.setSpacing(0) # 标题按钮(可展开/收起) - title_btn = QPushButton(f"{title}") + title_btn = QPushButton(f" {title}") # 默认有空格 if IconManager.icon_exists('down'): title_btn.setIcon(IconManager.get_icon('down')) else: - title_btn = QPushButton(f"▼ {title}") + title_btn.setText(f"▼ {title}") title_btn.setObjectName("navSectionTitle") title_btn.setCheckable(True) @@ -177,8 +184,8 @@ class Sidebar(QWidget): items_widget = QWidget() items_widget.setObjectName("navItems") items_layout = QVBoxLayout(items_widget) - items_layout.setContentsMargins(0, 0, 0, 0) - items_layout.setSpacing(0) + items_layout.setContentsMargins(0, 10, 0, 0) + items_layout.setSpacing(10) # 创建导航项 for icon, text, filter_type in items: @@ -194,13 +201,13 @@ class Sidebar(QWidget): if is_expanded: if IconManager.icon_exists('down'): title_btn.setIcon(IconManager.get_icon('down')) - title_btn.setText(f" {title}") + # 文本已经在初始化时设置了空格,不需要重新设置 else: title_btn.setText(f"▼ {title}") else: if IconManager.icon_exists('right'): title_btn.setIcon(IconManager.get_icon('right')) - title_btn.setText(f" {title}") + # 文本已经在初始化时设置了空格,不需要重新设置 else: title_btn.setText(f"▶ {title}") @@ -209,15 +216,16 @@ class Sidebar(QWidget): def create_nav_item(self, icon, text, filter_type): """创建导航项""" - item_btn = QPushButton(f" {text}") # 移除文字图标,只保留空格用于间距 + item_btn = QPushButton(text) # 直接使用文本,不显示图标 - # 设置真实图标 - if IconManager.icon_exists(filter_type): - item_btn.setIcon(IconManager.get_icon(filter_type, QSize(16, 16))) - item_btn.setIconSize(QSize(16, 16)) - else: - # 如果图标不存在,使用原来的文字图标 - item_btn.setText(f"{icon} {text}") + # 隐藏图标,不设置任何图标 + # 注释掉图标相关代码 + # if IconManager.icon_exists(filter_type): + # item_btn.setIcon(IconManager.get_icon(filter_type, QSize(16, 16))) + # item_btn.setIconSize(QSize(16, 16)) + # else: + # # 如果图标不存在,使用原来的文字图标 + # item_btn.setText(f"{icon} {text}") item_btn.setObjectName("navItem") item_btn.setCheckable(True) diff --git a/MetaCore/ui/styles.py b/MetaCore/ui/styles.py index 9d97b81..6baa996 100644 --- a/MetaCore/ui/styles.py +++ b/MetaCore/ui/styles.py @@ -52,1654 +52,445 @@ class StyleSheet: str: 完整的 QSS 样式表字符串 """ return """ - /* ======================================== - 全局样式定义 - ======================================== */ - - /* - * 全局 Widget 样式 - * 定义整个应用程序的基础外观,包括背景色、文字颜色和字体 - * - * 颜色说明: - * - #1e1e2e: 深蓝灰色背景,护眼且现代 - * - #ffffff: 纯白色文字,确保良好的对比度和可读性 - * - * 字体说明: - * 使用系统默认字体栈,确保在不同操作系统上的最佳显示效果 - */ + /* ---------- Base Theme ---------- */ QWidget { - background-color: #1e1e2e; /* 主背景色 - 深蓝灰 */ - color: #ffffff; /* 主文字色 - 纯白 */ - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - font-size: 14px; /* 标准字体大小 */ - } - - /* - * 主窗口样式 - * 设置应用程序主窗口的背景色,与全局样式保持一致 - */ - QMainWindow { - background-color: #1e1e2e; /* 与全局背景色一致 */ - } - - /* ======================================== - 侧边栏样式定义 - ======================================== */ - - /* - * 侧边栏主容器样式 - * 侧边栏是应用程序的主要导航区域,采用比主背景稍亮的颜色 - * 右侧边框用于与主内容区域分隔 - */ - Sidebar { - background-color: #252538; /* 侧边栏背景 - 比主背景稍亮 */ - border-right: 1px solid #3a3a4a; /* 右边框 - 分隔线 */ - } - - /* - * Logo 区域样式 - * 位于侧边栏顶部,显示应用程序标识 - * 底部边框用于与下方内容分隔 - */ - #logoWidget { - background-color: #252538; /* 与侧边栏背景一致 */ - border-bottom: 1px solid #3a3a4a; /* 底部分隔线 */ - } - - /* - * Logo 图标样式 - * 使用品牌主色调紫色,突出应用程序标识 - */ - #logoIcon { - font-size: 24px; /* 较大的图标尺寸 */ - background-color: transparent; /* 透明背景 */ - color: #8b5cf6; /* 品牌紫色 */ - font-weight: bold; /* 粗体强调 */ - } - - /* - * Logo 文字样式 - * 应用程序名称显示,使用白色确保可读性 - */ - #logoText { - font-size: 18px; /* 适中的文字大小 */ - font-weight: bold; /* 粗体强调 */ - color: #ffffff; /* 白色文字 */ - margin-left: 8px; /* 与图标的间距 */ - background-color: transparent; /* 透明背景 */ - } - - /* - * 快速操作区域样式 - * 包含创建项目和导入项目等主要操作按钮 - * 底部边框用于与导航菜单分隔 - */ - #quickActions { - background-color: #252538; /* 与侧边栏背景一致 */ - border-bottom: 1px solid #3a3a4a; /* 底部分隔线 */ - } - - /* - * 创建项目按钮样式 - * 主要操作按钮,使用品牌紫色突出显示 - * 包含悬停效果和微动画,提升用户体验 - */ - #createBtn { - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 16px; /* 内边距 */ - font-weight: 500; /* 中等粗细 */ - text-align: left; /* 左对齐 */ - font-size: 13px; /* 字体大小 */ - transition: all 0.2s ease; /* 平滑过渡动画 */ - } - - /* - * 创建按钮悬停效果 - * 颜色变深、轻微上移、添加阴影,增强交互反馈 - */ - #createBtn:hover { - background-color: #7c3aed; /* 更深的紫色 */ - transform: translateY(-1px); /* 向上移动1像素 */ - box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); /* 紫色阴影 */ - } - - /* - * 侧边栏导入项目按钮样式 - * 次要操作按钮,使用灰色调,相对低调 - * 与创建按钮保持一致的字体大小 - */ - #sidebarImportBtn { - background-color: #374151; /* 深灰色背景 */ - color: #d1d5db; /* 浅灰色文字 */ - border: 1px solid #4b5563; /* 灰色边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 16px; /* 内边距 */ - font-weight: 500; /* 中等粗细 */ - text-align: left; /* 左对齐 */ - font-size: 13px; /* 与创建按钮一致的字体大小 */ - transition: all 0.2s ease; /* 平滑过渡动画 */ - } - - /* - * 侧边栏导入按钮悬停效果 - * 背景变亮、文字变白、添加微动画 - */ - #sidebarImportBtn:hover { - background-color: #4b5563; /* 更亮的灰色 */ - color: white; /* 白色文字 */ - transform: translateY(-1px); /* 向上移动1像素 */ - box-shadow: 0 4px 12px rgba(75, 85, 99, 0.3); /* 灰色阴影 */ - } - - /* - * 导航分组标题样式 - * 用于分组显示导航项目,如"我的项目"、"项目类型"等 - * 使用大写字母和字母间距增强视觉层次 - */ - #navSectionTitle { - background-color: transparent; /* 透明背景 */ - color: #9ca3af; /* 中性灰色 */ - border: none; /* 无边框 */ - padding: 12px 20px; /* 内边距 */ - text-align: left; /* 左对齐 */ - font-weight: 600; /* 粗体 */ - font-size: 13px; /* 较小字体 */ - text-transform: uppercase; /* 大写字母 */ - letter-spacing: 0.5px; /* 字母间距 */ - transition: all 0.2s ease; /* 平滑过渡 */ - } - - /* - * 导航分组标题悬停效果 - * 背景变亮,文字变白,增强交互反馈 - */ - #navSectionTitle:hover { - background-color: #3a3a4a; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - } - - /* - * 导航项目样式 - * 具体的导航选项,如"项目概览"、"收藏项目"等 - * 左侧缩进表示层级关系,圆角和边距增强视觉效果 - */ - #navItem { - background-color: transparent; /* 透明背景 */ - color: #9ca3af; /* 中性灰色 */ - border: none; /* 无边框 */ - padding: 12px 20px 12px 40px; /* 左侧缩进40px */ - text-align: left; /* 左对齐 */ - font-size: 14px; /* 标准字体大小 */ - border-radius: 8px; /* 圆角 */ - margin: 2px 12px; /* 外边距 */ - transition: all 0.2s ease; /* 平滑过渡 */ - } - - /* - * 导航项目悬停效果 - * 背景变亮、文字变白、轻微右移,增强交互感 - */ - #navItem:hover { - background-color: #3a3a4a; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - transform: translateX(2px); /* 向右移动2像素 */ - } - - /* - * 导航项目选中状态 - * 当前选中的导航项,使用品牌色突出显示 - * 左边框和背景色变化表示选中状态 - */ - #navItem:checked { - background-color: rgba(139, 92, 246, 0.15); /* 半透明紫色背景 */ - color: #8b5cf6; /* 品牌紫色文字 */ - border-left: 3px solid #8b5cf6; /* 左侧紫色边框 */ - font-weight: 500; /* 中等粗细 */ - } - - /* - * 用户信息区域样式 - * 位于侧边栏底部,显示当前用户信息 - * 顶部边框用于与上方导航区域分隔 - */ - #userInfo { - background-color: #252538; /* 与侧边栏背景一致 */ - border-top: 1px solid #3a3a4a; /* 顶部分隔线 */ - } - - /* - * 用户头像样式 - * 圆形头像,使用品牌色作为背景 - * 通常显示用户名首字母或头像图片 - */ - #userAvatar { - font-size: 14px; /* 头像内文字大小 */ - font-weight: bold; /* 粗体文字 */ - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色文字 */ - border-radius: 16px; /* 圆形头像 */ - border: 2px solid #7c3aed; /* 深紫色边框 */ - } - - /* - * 用户名样式 - * 显示在头像旁边的用户名文字 - */ - #userName { - color: #ffffff; /* 白色文字 */ - font-weight: bold; /* 粗体强调 */ - margin-left: 8px; /* 与头像的间距 */ - background-color: transparent; /* 透明背景 */ - } - - /* - * 用户下拉菜单指示器样式 - * 小箭头或图标,表示可以展开用户菜单 - */ - #userDropdown { - font-size: 10px; /* 较小的图标 */ - color: #888888; /* 灰色 */ - background-color: transparent; /* 透明背景 */ - } - - /* - * 导航滚动区域样式 - * 当导航项目过多时提供滚动功能 - * 设置为透明以保持视觉一致性 - */ - #navScrollArea { - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - } - - /* - * 导航内容容器样式 - * 包含所有导航项目的容器 - */ - #navWidget { - background-color: transparent; /* 透明背景 */ - } - - /* - * 导航分组容器样式 - * 每个导航分组的容器 - */ - #navSection { - background-color: transparent; /* 透明背景 */ - } - - /* - * 导航项目列表容器样式 - * 包含具体导航项目的容器 - */ - #navItems { - background-color: transparent; /* 透明背景 */ - } - - /* ======================================== - 项目区域样式定义 - ======================================== */ - - /* - * 工具栏样式 - * 位于项目区域顶部,包含搜索、筛选、视图切换等功能 - * 使用与侧边栏相同的背景色保持一致性 - */ - #toolbar { - background-color: #252538; /* 深色背景 */ - border-bottom: 1px solid #3a3a4a; /* 底部分隔线 */ - } - - /* - * 内容头部样式 - * 包含面包屑导航和页面标题等信息 - * 调整为更紧凑的高度 - */ - #contentHeader { - background-color: #1e1e2e; /* 主背景色 */ - min-height: 40px; /* 设置最小高度,保持紧凑 */ - } - - /* ======================================== - 面包屑导航样式定义 - ======================================== */ - - /* - * 面包屑导航容器样式 - * 确保面包屑导航区域有统一的背景和布局 - */ - #breadcrumbContainer { - background-color: transparent; /* 透明背景,继承工具栏背景 */ - border: none; /* 无边框 */ - padding: 0; /* 无内边距 */ - margin: 0; /* 无外边距 */ - } - - /* - * 面包屑导航项目样式 - * 显示导航路径中的非当前项目,使用灰色表示 - * 确保背景透明,与工具栏背景保持一致 - */ - #breadcrumbItem { - color: #9ca3af; /* 中性灰色 */ - font-size: 14px; /* 标准字体大小 */ - background-color: transparent; /* 透明背景,确保一致性 */ - border: none; /* 无边框 */ - padding: 2px 0; /* 轻微的上下内边距,保持对齐 */ - margin: 0; /* 无外边距 */ - font-family: inherit; /* 继承字体 */ - } - - /* - * 面包屑分隔符样式 - * 用于分隔导航路径中的各个项目,通常是"/"或">" - * 确保背景透明,与其他面包屑元素保持一致 - */ - #breadcrumbSeparator { - color: #6b7280; /* 较深的灰色 */ - font-size: 14px; /* 标准字体大小 */ - margin: 0 8px; /* 左右间距 */ - background-color: transparent; /* 透明背景,确保一致性 */ - border: none; /* 无边框 */ - padding: 2px 0; /* 与其他元素相同的上下内边距 */ - font-family: inherit; /* 继承字体 */ - } - - /* - * 面包屑当前项目样式 - * 显示当前所在页面,使用白色突出显示 - * 确保背景透明,与其他面包屑元素保持一致 - */ - #breadcrumbCurrent { - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 标准字体大小 */ - font-weight: 500; /* 中等粗细 */ - background-color: transparent; /* 透明背景,确保一致性 */ - border: none; /* 无边框 */ - padding: 2px 0; /* 与其他元素相同的上下内边距 */ - margin: 0; /* 无外边距 */ - font-family: inherit; /* 继承字体 */ - } - - /* ======================================== - 按钮样式定义 - ======================================== */ - - /* - * 图标按钮样式 (工具栏版本) - * 用于工具栏中的图标按钮,如搜索、筛选、视图切换等 - * 采用透明背景和边框设计,悬停时有微妙的交互效果 - */ - #iconBtn { - background-color: transparent; /* 透明背景 */ - border: 1px solid #3a3a4a; /* 深灰边框 */ - border-radius: 8px; /* 圆角设计 */ - color: #9ca3af; /* 中性灰色图标 */ - padding: 8px 12px; /* 内边距 */ - font-size: 14px; /* 图标大小 */ - min-width: 40px; /* 最小宽度 */ - min-height: 40px; /* 最小高度 */ - transition: all 0.2s ease; /* 平滑过渡动画 */ - } - - /* - * 图标按钮悬停效果 - * 背景变亮、图标变白、边框变亮、轻微上移 - */ - #iconBtn:hover { - background-color: #3a3a4a; /* 深灰背景 */ - color: #ffffff; /* 白色图标 */ - border-color: #4b5563; /* 更亮的边框 */ - transform: translateY(-1px); /* 向上移动1像素 */ - } - - /* - * 主要按钮样式 - * 用于重要操作,如"创建项目"、"保存"、"确认"等 - * 使用品牌紫色突出显示,具有强烈的视觉吸引力 - */ - #primaryBtn { - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 24px; /* 内边距,与次要按钮一致 */ - font-weight: 500; /* 中等粗细 */ - font-size: 14px; /* 标准字体大小 */ - transition: all 0.2s ease; /* 平滑过渡动画 */ - } - - /* - * 主要按钮悬停效果 - * 颜色变深、轻微上移、添加紫色阴影,增强交互反馈 - */ - #primaryBtn:hover { - background-color: #7c3aed; /* 更深的紫色 */ - transform: translateY(-1px); /* 向上移动1像素 */ - box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); /* 紫色阴影 */ - } - - /* - * 主要按钮禁用状态 - * 当按钮不可用时的样式,使用灰色表示 - */ - #primaryBtn:disabled { - background-color: #4a4a4a; /* 灰色背景 */ - color: #888888; /* 灰色文字 */ - transform: none; /* 无变换效果 */ - box-shadow: none; /* 无阴影 */ - cursor: not-allowed; /* 禁用光标 */ - } - - /* - * 导入项目按钮样式 - * 用于从本地或远程源导入项目的按钮 - * 使用灰色作为主要颜色,与主要按钮高度保持一致 - */ - #importBtn { - background-color: #374151; /* 深灰色背景 */ - color: white; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 24px; /* 内边距,与主要按钮一致 */ - font-weight: 500; /* 中等粗细 */ - font-size: 14px; /* 标准字体大小 */ - transition: all 0.2s ease; /* 平滑过渡动画 */ - } - - /* - * 导入项目按钮悬停效果 - * 颜色变深、轻微上移、添加黑色阴影,增强交互反馈 - */ - #importBtn:hover { - background-color: #4b5563; /* 更深的灰色 */ - transform: translateY(-1px); /* 向上移动1像素 */ - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); /* 黑色阴影 */ - } - - /* - * 内容标题样式 - * 用于页面或区域的主标题,如"项目概览"、"我的项目"等 - * 使用较大的字体和粗体突出显示层级 - */ - #contentTitle { - font-size: 20px; /* 大标题字体 */ - font-weight: bold; /* 粗体强调 */ - color: #ffffff; /* 白色文字 */ - } - - /* - * 视图切换按钮样式 - * 用于在不同视图模式之间切换,如网格视图、列表视图等 - * 采用透明背景设计,通过边框和颜色变化表示状态 - */ - #viewBtn { - background-color: transparent; /* 透明背景 */ - border: 1px solid #3a3a4a; /* 深灰边框 */ - border-radius: 6px; /* 圆角设计 */ - padding: 6px; /* 减少内边距:8px->6px */ - color: #9ca3af; /* 中性灰色图标 */ - font-size: 14px; /* 图标大小 */ - min-width: 32px; /* 减少最小宽度:40px->32px */ - min-height: 32px; /* 减少最小高度:40px->32px */ - } - - /* - * 视图按钮悬停效果 - * 背景变深、图标变白、边框变亮,提供清晰的交互反馈 - */ - #viewBtn:hover { - background-color: #3a3a4a; /* 深灰背景 */ - color: #ffffff; /* 白色图标 */ - border-color: #4b5563; /* 更亮的边框 */ - } - - /* - * 视图按钮选中状态 - * 当前激活的视图模式,使用品牌色突出显示 - */ - #viewBtn:checked { - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色图标 */ - border-color: #8b5cf6; /* 紫色边框 */ - } - - /* - * 搜索区域样式 - * 包含搜索输入框和相关控件的容器区域 - * 使用与工具栏相同的背景色保持视觉一致性 - * 调整为更紧凑的高度 - */ - #searchArea { - background-color: #252538; /* 深色背景,与工具栏一致 */ - border-bottom: 1px solid #3a3a4a; /* 底部分隔线 */ - padding: 8px 0; /* 减少上下内边距:15px->8px */ - min-height: 36px; /* 设置最小高度,保持紧凑 */ - } - - /* - * 搜索输入框样式 - * 主要的搜索功能输入框,支持实时搜索和筛选 - * 采用深色主题设计,聚焦时有品牌色高亮效果 - */ - #searchInput { - background-color: #1e1e2e; /* 深色背景 */ - border: 1px solid #3a3a4a; /* 深灰边框 */ - border-radius: 6px; /* 减小圆角:8px->6px */ - padding: 6px 12px; /* 减小内边距,适合工具栏 */ - color: #ffffff; /* 白色文字 */ - font-size: 13px; /* 稍小的字体 */ - min-width: 200px; /* 减小最小宽度 */ - max-width: 250px; /* 限制最大宽度 */ - height: 28px; /* 减小高度,与视图按钮协调 */ - } - - /* - * 搜索输入框聚焦状态 - * 当用户点击或聚焦输入框时的样式 - * 使用品牌色边框和光晕效果,提供清晰的视觉反馈 - */ - #searchInput:focus { - border-color: #8b5cf6; /* 品牌紫色边框 */ - outline: none; /* 移除默认轮廓 */ - box-shadow: 0 0 0 1px rgba(139, 92, 246, 0.3); /* 减小光晕效果 */ - } - - /* - * 排序和类型筛选下拉框样式 - * 用于项目排序(按时间、名称等)和类型筛选的下拉选择框 - * 采用与搜索框相似的设计风格保持一致性 - * 调整为与搜索框一致的高度 - */ - #sortCombo, #typeCombo { - background-color: #1e1e2e; /* 深色背景 */ - border: 1px solid #3a3a4a; /* 深灰边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 8px 12px; /* 减少内边距:10px->8px,与搜索框一致 */ - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 标准字体大小 */ - min-width: 150px; /* 最小宽度 */ - height: 32px; /* 设置与搜索框一致的高度 */ - } - - /* - * 下拉框聚焦状态 - * 当用户点击下拉框时的样式,使用品牌色高亮 - */ - #sortCombo:focus, #typeCombo:focus { - border-color: #8b5cf6; /* 品牌紫色边框 */ - outline: none; /* 移除默认轮廓 */ - } - - /* - * 下拉框按钮区域样式 - * 移除默认的下拉按钮边框,保持简洁外观 - */ - #sortCombo::drop-down, #typeCombo::drop-down { - border: none; /* 无边框 */ - } - - /* - * 下拉箭头样式 - * 自定义下拉箭头图标,使用CSS绘制的三角形 - * 替换默认的系统箭头图标 - */ - #sortCombo::down-arrow, #typeCombo::down-arrow { - image: none; /* 移除默认图标 */ - border-left: 5px solid transparent; /* 左边透明边框 */ - border-right: 5px solid transparent; /* 右边透明边框 */ - border-top: 5px solid #cccccc; /* 顶部边框形成向下箭头 */ - margin-right: 5px; /* 右边距 */ - } - - /* - * 项目容器样式 - * 包含所有项目卡片的主容器区域 - * 使用主背景色保持与整体设计的一致性 - */ - #projectsContainer { - background-color: #1e1e2e; /* 主背景色 */ - } - - /* ======================================== - 项目卡片样式定义 - ======================================== */ - /* 整个卡片样式 */ - #projectCard { - background-color: #8b5cf6; /* 紫色卡片背景 */ - border: 1px solid #5a5a6a; - border-radius: 16px; - } - - /* 悬停效果 - 整个卡片背景变化 */ - #projectCard:hover { - background-color: #7c3aed; - border-color: #6a6a7a; - } - - /* 程序化悬停状态 */ - #projectCard[hover="true"] { - background-color: #6d28d9; - border-color: #5a5a7a; - } - - /* 待删除状态 */ - #projectCard[status="pending_delete"] { - background-color: #4b5563; - border-color: #3f4a5a; - opacity: 0.7; - } - /* 待删除 悬浮 状态 */ - #projectCard[status="pending_delete"]:hover { - background-color: #7c3aed; - border-color: #3f4a5a; - opacity: 0.7; - } - - /* 头部样式 */ - #projectHeader { - background-color: transparent; /* 透明背景,继承卡片背景 */ - border-top-left-radius: 16px; - border-top-right-radius: 16px; - } - - /* 悬停时头部背景保持透明 */ - #projectCard:hover #projectHeader { - background-color: transparent; /* 保持透明,让卡片背景显示 */ - } - - /* 底部样式 */ - #projectFooter { - background-color: transparent; /* 透明背景,继承卡片背景 */ - border-bottom-left-radius: 16px; - border-bottom-right-radius: 16px; - } - - /* 悬停时底部背景保持透明 */ - #projectCard:hover #projectFooter { - background-color: transparent; /* 保持透明,让卡片背景显示 */ - } - - /* 图片区域样式 - 保持深色背景 */ - #projectImage { - background-color: #3a3a4a; /* 固定深色背景 */ - border-radius: 12px; - min-height: 100px; - max-height: 120px; - margin: 0; - } - - /* 悬停时图片区域保持深色但稍微变亮 */ - #projectCard:hover #projectImage { - background-color: #4a4a5a; /* 稍亮的深色 */ - } - - /* 其他样式保持不变 */ - #projectTitle { + background-color: #0f1115; + color: #f3f4f8; + font-family: "Inter", "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 14px; - font-weight: 600; - color: #ffffff; - background-color: transparent; } - - #menuBtn { + + QMainWindow { + background-color: #0f1115; + } + + #sidebar { + background-color: #000000; + border-right: 1px solid #1c2029; + width: 313px; + } + + #logoWidget { background-color: transparent; - border: none; + border-bottom: 1px solid rgba(84, 89, 98, 0.8); + margin: 0 46px 0 37px; + } + + #logoIcon { + background-color: #2a2f3b; + border: 1px solid #303543; border-radius: 4px; - color: #e0e0ff; + min-width: 80px; + min-height: 80px; + } + + #logoText { + background-color: transparent; + color: #FFFFFF; + font-family: "Inter"; + font-size: 24px; + font-weight: 500; /* Medium weight in Qt */ + letter-spacing: 0.4px; + } + + #quickActions { + background-color: transparent; + } + + QPushButton#createBtn, + QPushButton#sidebarImportBtn { + background-color: rgba(84, 89, 98, 0.2); + border: 1px solid #979fad; + border-radius: 6px; + color: #ffffff; + font-family: "Inter"; + font-weight: 300; font-size: 16px; + letter-spacing: 0.8px; + padding: 0px 16px; + text-align: center; + min-height: 36px; + max-height: 36px; } - - #menuBtn:hover { - background-color: rgba(255, 255, 255, 0.2); + + QPushButton#createBtn:hover, + QPushButton#sidebarImportBtn:hover { + background-color: rgba(84, 89, 98, 0.3); + border-color: #a5abb8; } - - #deleteBtn { + + QPushButton#createBtn:pressed, + QPushButton#sidebarImportBtn:pressed { + background-color: rgba(84, 89, 98, 0.4); + border-color: #b0b6c3; + } + + #navScrollArea { + background-color: #000000; + border: none; + } + + #navWidget { + background-color: #000000; + } + + #navSection { + margin-top: 0px; + } + + QPushButton#navSectionTitle { + border: none; + background: #000000; + color: #ffffff; + font-family: "Inter"; + font-size: 16px; + font-weight: 500; + letter-spacing: 0.8px; + padding: 0px 37px; + text-align: left; + min-height: 20px; + max-height: 20px; + } + + QWidget#navItems { + background: #000000; + } + + QPushButton#navItem { + border: none; + border-left: 3px solid transparent; + border-radius: 0px; + background: #000000; + color: #ebebeb; + font-family: "Inter"; + font-size: 14px; + font-weight: 300; + letter-spacing: 0.7px; + padding: 0px 46px 0px 67px; + text-align: left; + min-height: 26px; + max-height: 26px; + } + + QPushButton#navItem:hover { + background-color: #000000; + color: #ffffff; + } + + QPushButton#navItem:checked { + background-color: #000000; + color: #ffffff; + border-left: 3px solid transparent; + font-weight: 300; + } + + QPushButton#navItem::icon { + padding-right: 8px; + } + + /* ---------- Content Area ---------- */ + #projectArea { + background-color: #000000; + } + + #contentHeader { + background: transparent; + border-bottom: 1px solid #1f2532; + } + + #breadcrumbContainer { + background: 19191b; + } + + #breadcrumbBase { + background: transparent; + color: rgba(255, 255, 255, 0.7); + font-family: "Inter"; + font-size: 20px; + font-weight: 400; + letter-spacing: 1px; + } + + #breadcrumbSeparator { + background: transparent; + color: rgba(255, 255, 255, 0.7); + padding: 0 8px; + font-family: "Inter"; + font-size: 20px; + font-weight: 400; + letter-spacing: 1px; + } + + #breadcrumbCurrent { + background: transparent; + color: #ffffff; + font-family: "Inter"; + font-size: 24px; + font-weight: 500; + letter-spacing: 1.2px; + } + + QLineEdit#searchInput { + background-color: rgba(84, 89, 98, 0.2); + border: 1px solid rgba(92, 97, 105, 0.8); + border-radius: 4px; + color: #5c6169; + font-family: "Inter"; + font-size: 18px; + font-weight: 300; + letter-spacing: 0.9px; + padding: 0px 16px 0px 10px; + min-height: 39px; + max-height: 39px; + } + + QLineEdit#searchInput:focus { + border-color: rgba(92, 97, 105, 1.0); + background-color: rgba(84, 89, 98, 0.25); + } + + QLineEdit#searchInput::placeholder { + color: #5c6169; + font-family: "Inter"; + font-size: 18px; + font-weight: 300; + letter-spacing: 0.9px; + } + + QScrollArea#projectScrollArea { + background: transparent; + border: none; + } + + #projectsContainer { + background-color: transparent; + } + + #projectCard { background-color: transparent; border: none; - border-radius: 6px; - color: #ff6b6b; - font-size: 16px; - font-weight: bold; + border-radius: 5px; + min-width: 276px; + max-width: 276px; + min-height: 191px; + max-height: 191px; } - - #deleteBtn:hover { - background-color: rgba(255, 255, 255, 0.2); + + #projectCard:hover { + /* 悬停效果通过子组件实现 */ } - - #projectImageContainer { - background-color: transparent; + + #projectHeader { + background: transparent; + border-bottom: none; + } + + #projectTitle { + color: #d4d4d4; + font-family: "Inter"; + font-size: 17.3px; + font-weight: 500; + letter-spacing: 0.865px; + } + + QPushButton#menuBtn { + background: #424347; + border: 1px solid rgba(235, 235, 235, 0.2); + color: #ebebeb; padding: 0px; + border-radius: 1px; } - + + QPushButton#menuBtn:hover { + background-color: rgba(235, 235, 235, 0.1); + border-color: rgba(235, 235, 235, 0.3); + } + + /* 新的覆盖按钮样式 - 完全去掉外层圈 */ + QPushButton#overlayInfoBtn, QPushButton#overlayDeleteBtn { + background-color: transparent; + border: none; + border-radius: 0px; + color: #ffffff; + font-size: 12px; + font-weight: 400; + outline: none; + padding: 0px; + margin: 0px; + } + + QPushButton#overlayInfoBtn:hover, QPushButton#overlayDeleteBtn:hover { + background-color: transparent; + border: none; + outline: none; + } + + QPushButton#overlayInfoBtn:pressed, QPushButton#overlayDeleteBtn:pressed { + background-color: transparent; + border: none; + outline: none; + } + + QPushButton#overlayInfoBtn:focus, QPushButton#overlayDeleteBtn:focus { + background-color: transparent; + border: none; + outline: none; + } + + QPushButton#overlayDeleteBtn { + color: #ff6b6b; + } + + QPushButton#overlayDeleteBtn:hover { + background-color: rgba(255, 107, 107, 0.1); + border-color: rgba(255, 107, 107, 0.3); + } + + #projectImageContainer { + padding: 0 20px; + } + + #projectImage { + background-color: #292f3d; + border-radius: 5px; + min-height: 140px; + } + #projectIcon { font-size: 36px; - color: #ffffff; - padding: 10px; + color: #596074; } - + + #projectFooter { + background: #424347; + border-top: none; + margin-top: 0px; + padding: 12px 20px; + min-height: 53px; + max-height: 53px; + } + #projectDate { - font-size: 11px; - color: #e0e0ff; - font-weight: 400; - background-color: transparent; - } - - /* ======================================== - 对话框样式定义 - ======================================== */ - - /* - * 对话框主容器样式 - * 所有弹出对话框的基础样式 - * 采用与主应用一致的深色主题和圆角设计 - */ - QDialog { - background-color: #1e1e2e; /* 与主应用背景一致 */ - border: 1px solid #3a3a4a; /* 深灰边框,与侧边栏分隔线一致 */ - border-radius: 12px; /* 圆角设计 */ - color: #ffffff; /* 白色文字 */ + color: #d4d4d4; + font-family: "Inter"; + font-size: 12.36px; + font-weight: 300; + letter-spacing: 0.618px; } - /* - * 模板选择区域样式 - * 对话框左侧的模板选择区域 - * 使用与侧边栏相似的背景色,右边框与项目信息区域分隔 - */ - #templateSection { - background-color: #252538; /* 与侧边栏背景一致 */ - border-right: 1px solid #3a3a4a; /* 右边框分隔线 */ + /* 新的覆盖层样式 */ + #overlayProjectTitle { + color: #d4d4d4; + font-family: "Inter", sans-serif; + font-size: 17px; + font-weight: 500; + background: transparent; } - /* - * 项目信息区域样式 - * 对话框右侧的项目信息输入区域 - * 使用主应用背景色,与左侧形成层次感 - */ - #projectInfoSection { - background-color: #1e1e2e; /* 与主应用背景一致 */ + #overlayProjectDate, #overlayProjectSize { + color: #d4d4d4; + font-family: "Inter", sans-serif; + font-size: 12px; + font-weight: 300; + background: transparent; } - - - - - /* - * 区域标题样式 - * 用于"选择模板"、"项目信息"等区域标题 - * 使用中等大小字体和粗体突出显示 - */ - #sectionTitle { - font-size: 16px; /* 中等字体大小 */ - font-weight: 600; /* 半粗体 */ - color: #ffffff; /* 白色文字 */ - margin-bottom: 20px; /* 底部间距 */ + #bottomOverlay { + background-color: rgba(66, 67, 71, 0.9); + border-radius: 0px; } - /* - * 模板选项样式 - * 每个可选择的项目模板的容器 - * 支持悬停和选中状态的视觉反馈,使用与主应用一致的颜色 - * 采用固定尺寸设计,确保多个模板时布局一致 - */ - #templateItem { - background-color: #2a2a3a; /* 比模板区域稍亮的背景 */ - border: 2px solid transparent; /* 透明边框,选中时显示 */ - border-radius: 12px; /* 圆角设计 */ - padding: 0px; /* 移除内边距,由内部布局控制 */ - text-align: center; /* 文字居中 */ - width: 180px; /* 固定宽度 */ - height: 140px; /* 固定高度 */ - max-width: 180px; /* 最大宽度限制 */ - max-height: 140px; /* 最大高度限制 */ - min-width: 180px; /* 最小宽度限制 */ - min-height: 140px; /* 最小高度限制 */ - } - - /* - * 模板选项悬停效果 - * 边框高亮和背景变亮,提供交互反馈 - */ - #templateItem:hover { - border-color: #8b5cf6; /* 品牌紫色边框 */ - background-color: #3a3a4a; /* 更亮的背景 */ - } - - /* - * 模板选项选中状态 - * 当前选中的模板,使用品牌色边框和半透明背景 - */ - #templateItem:checked { - border-color: #8b5cf6; /* 品牌紫色边框 */ - background-color: rgba(139, 92, 246, 0.15); /* 稍深的半透明紫色背景 */ - } - - /* - * 模板选项按下状态 - * 当用户点击模板按钮时的样式 - */ - #templateItem:pressed { - background-color: rgba(139, 92, 246, 0.25); /* 更深的紫色背景 */ - border-color: #8b5cf6; /* 品牌紫色边框 */ - } - - /* - * 模板选项聚焦状态 - * 当模板按钮获得焦点时的样式(键盘导航) - */ - #templateItem:focus { - border-color: #8b5cf6; /* 品牌紫色边框 */ - outline: none; /* 移除默认轮廓 */ - } - - /* - * 模板图标样式 - * 模板按钮中的图标显示 - * 使用较大的字体尺寸突出显示 - */ - #templateIcon { - font-size: 36px; /* 较大的图标尺寸 */ - color: #ffffff; /* 白色图标 */ - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - padding: 0; /* 无内边距 */ - } - - /* - * 模板名称样式 - * 显示模板名称的文字 - * 确保在不同状态下都有良好的可读性 - */ - #templateName { - font-size: 14px; /* 标准字体大小 */ - font-weight: 500; /* 中等粗细 */ - color: #ffffff; /* 白色文字 */ - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - padding: 0; /* 无内边距 */ - margin-top: 4px; /* 与图标的间距 */ - } - - /* - * 确保模板按钮内的所有子元素背景透明 - * 防止子元素覆盖父元素的背景样式 - */ - #templateItem QLabel { - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - } - - /* - * 模板按钮布局容器样式 - * 确保内部布局不影响背景显示 - */ - #templateItem QVBoxLayout { - background-color: transparent; /* 透明背景 */ - } - - /* - * 模板容器样式 - * 包含所有模板按钮的网格容器 - * 支持固定尺寸的模板按钮布局 - */ - #templatesContainer { - background-color: transparent; /* 透明背景,继承父容器背景 */ - border: none; /* 无边框 */ - padding: 10px; /* 内边距 */ - } - - /* - * 模板滚动区域样式 - * 确保滚动区域能够正确显示固定尺寸的模板按钮 - */ - QScrollArea[objectName="templateScrollArea"] { - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - min-height: 200px; /* 最小高度,确保至少显示一行模板 */ - } - - /* - * 模板描述区域样式 - * 显示选中模板详细描述的文本区域 - * 使用与主应用一致的深色背景和圆角设计,增强可读性 - */ - #templateDescription { - background-color: #2a2a3a; /* 与模板项背景一致 */ - border: 1px solid #3a3a4a; /* 添加边框增强层次感 */ - border-radius: 8px; /* 圆角设计 */ - padding: 15px; /* 内边距 */ - margin-bottom: 20px; /* 底部间距 */ - color: #e5e5e5; /* 更亮的文字颜色 */ - line-height: 1.5; /* 行高增强可读性 */ - } - - /* - * 表单标签样式 - * 表单输入框上方的标签文字 - * 使用白色和中等粗细突出显示 - */ - #formLabel { - font-size: 14px; /* 标准字体大小 */ - font-weight: 500; /* 中等粗细 */ - color: #ffffff; /* 白色文字 */ - margin-bottom: 8px; /* 底部间距 */ - } - - /* - * 表单输入框样式 - * 用于项目名称、路径等单行输入的文本框 - * 采用与搜索框一致的深色主题设计,聚焦时有品牌色高亮 - */ - #formInput { - background-color: #2a2a3a; /* 与模板项背景一致 */ - border: 1px solid #3a3a4a; /* 与应用边框一致 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 16px; /* 内边距,与搜索框一致 */ - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 标准字体大小 */ - } - - /* - * 表单输入框聚焦状态 - * 当用户点击或聚焦输入框时的样式 - * 使用与搜索框一致的聚焦效果 - */ - #formInput:focus { - border-color: #8b5cf6; /* 品牌紫色边框 */ - outline: none; /* 移除默认轮廓 */ - box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.2); /* 紫色光晕效果 */ - } - - /* - * 表单输入框错误状态 - * 当输入验证失败时的样式 - */ - #formInput[error="true"] { - border-color: #ff4444; /* 红色边框 */ - background-color: rgba(255, 68, 68, 0.1); /* 半透明红色背景 */ - } - - /* - * 表单输入框成功状态 - * 当输入验证成功时的样式 - */ - #formInput[valid="true"] { - border-color: #22c55e; /* 绿色边框 */ - background-color: rgba(34, 197, 94, 0.1); /* 半透明绿色背景 */ - } - - /* - * 错误提示标签样式 - * 在输入框下方显示一行小红字的错误提示 - * 简洁明了,不占用过多空间 - */ - #errorLabel { - color: #ff4444; /* 红色文字 */ - font-size: 11px; /* 小字体 */ - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - padding: 2px 0 0 0; /* 仅顶部小间距 */ - margin: 0; /* 无外边距 */ - height: 18px; /* 固定高度,一行文字 */ - line-height: 16px; /* 行高 */ - font-weight: normal; /* 正常字重 */ - text-overflow: ellipsis; /* 文字过长时显示省略号 */ - white-space: nowrap; /* 不换行 */ - overflow: hidden; /* 隐藏溢出内容 */ - } - - /* - * 表单文本区域样式 - * 用于项目描述等多行输入的文本区域 - * 样式与单行输入框保持一致 - */ - #formTextArea { - background-color: #2a2a3a; /* 与输入框背景一致 */ - border: 1px solid #3a3a4a; /* 与输入框边框一致 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 16px; /* 内边距,与输入框一致 */ - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 标准字体大小 */ - min-height: 80px; /* 最小高度 */ - } - - /* - * 表单文本区域聚焦状态 - * 与输入框聚焦状态保持一致 - */ - #formTextArea:focus { - border-color: #8b5cf6; /* 品牌紫色边框 */ - outline: none; /* 移除默认轮廓 */ - box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.2); /* 紫色光晕效果 */ - } - - /* - * 浏览按钮样式 - * 用于选择文件或文件夹的浏览按钮 - * 使用品牌色突出显示重要操作 - */ - #browseBtn { - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 8px; /* 圆角设计 */ - font-size: 14px; /* 标准字体大小 */ - } - - /* - * 浏览按钮悬停效果 - * 颜色变深,增强交互反馈 - */ - #browseBtn:hover { - background-color: #7c3aed; /* 更深的紫色 */ - } - - /* - * 对话框按钮区域样式 - * 对话框底部的按钮容器区域 - * 使用与侧边栏一致的背景色,顶部边框与内容区域分隔 - */ - #buttonArea { - background-color: #252538; /* 与侧边栏背景一致 */ - border-top: 1px solid #3a3a4a; /* 顶部分隔线 */ - } - - /* - * 次要按钮样式 - * 用于"取消"、"返回"等次要操作的按钮 - * 采用透明背景和边框设计,相对低调 - */ - #secondaryBtn { - background-color: transparent; /* 透明背景 */ - border: 1px solid #4a4a4a; /* 深灰边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 12px 24px; /* 内边距 */ - color: #cccccc; /* 浅灰色文字 */ - font-weight: 500; /* 中等粗细 */ - } - - /* - * 次要按钮悬停效果 - * 背景变深、文字变白,提供交互反馈 - */ - #secondaryBtn:hover { - background-color: #3a3a3a; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - } - - /* ======================================== - 对话框滚动区域样式 - ======================================== */ - - /* - * 对话框内滚动区域样式 - * 确保滚动区域与对话框背景融合 - */ - QDialog QScrollArea { - background-color: transparent; /* 透明背景 */ - border: none; /* 无边框 */ - } - - /* - * 对话框滚动区域视口样式 - * 滚动内容的实际显示区域 - */ - QDialog QScrollArea > QWidget > QWidget { - background-color: transparent; /* 透明背景 */ - } - - /* ======================================== - 项目设置页面样式 - ======================================== */ - - /* - * 页面标题样式 - * 设置页面的主标题 - */ - #pageTitle { - font-size: 24px; /* 大字体 */ - font-weight: bold; /* 粗体 */ - color: #ffffff; /* 白色文字 */ - margin-bottom: 5px; /* 底部间距 */ - } - - /* - * 页面副标题样式 - * 设置页面的描述文字 - */ - #pageSubtitle { - font-size: 14px; /* 标准字体 */ - color: #9ca3af; /* 灰色文字 */ - margin-bottom: 0px; /* 无底部间距 */ - } - - /* - * 设置分组框样式 - * 用于组织不同的设置选项 - */ - #settingsGroup { - background-color: #252538; /* 深色背景 */ - border: 1px solid #3a3a4a; /* 边框 */ - border-radius: 12px; /* 圆角 */ - padding: 20px; /* 内边距 */ - margin: 10px 0; /* 上下间距 */ - font-size: 16px; /* 标题字体大小 */ - font-weight: 600; /* 标题字体粗细 */ - color: #ffffff; /* 标题文字颜色 */ - } - - /* - * 设置描述文字样式 - * 用于说明设置选项的作用 - */ - #settingsDescription { - color: #9ca3af; /* 灰色文字 */ - font-size: 13px; /* 小字体 */ - line-height: 1.4; /* 行高 */ - } - - /* - * 设置标签样式 - * 用于设置项的标签文字 - */ - #settingsLabel { - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 标准字体 */ - font-weight: 500; /* 中等粗细 */ - } - - /* - * 路径输入框样式 - * 用于显示和输入文件路径 - */ - #pathInput { - background-color: #1e1e2e; /* 深色背景 */ - border: 1px solid #3a3a4a; /* 边框 */ - border-radius: 8px; /* 圆角 */ - padding: 10px 12px; /* 内边距 */ - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 字体大小 */ - min-height: 20px; /* 最小高度 */ - } - - /* - * 路径输入框聚焦状态 - */ - #pathInput:focus { - border-color: #8b5cf6; /* 品牌色边框 */ - outline: none; /* 移除默认轮廓 */ - } - - /* - * 浏览按钮样式 - * 用于打开文件夹选择对话框 - * 调整为更紧凑的尺寸 - */ - #browseBtn { - background-color: #374151; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 6px; /* 减小圆角:8px->6px */ - padding: 8px 12px; /* 减小内边距:10px 16px->8px 12px */ - font-size: 13px; /* 减小字体:14px->13px */ - font-weight: 500; /* 字体粗细 */ - min-width: 60px; /* 减小最小宽度:80px->60px */ - max-height: 32px; /* 限制最大高度 */ - } - - /* - * 浏览按钮悬停效果 - */ - #browseBtn:hover { - background-color: #4b5563; /* 更亮的背景 */ - } - - /* - * 重置按钮样式 - * 调整为更紧凑的尺寸 - */ - #resetBtn { - background-color: transparent; /* 透明背景 */ - color: #9ca3af; /* 灰色文字 */ - border: 1px solid #4a4a4a; /* 边框 */ - border-radius: 6px; /* 减小圆角:8px->6px */ - padding: 8px 12px; /* 减小内边距:10px 16px->8px 12px */ - font-size: 13px; /* 减小字体:14px->13px */ - min-width: 50px; /* 减小最小宽度:60px->50px */ - max-height: 32px; /* 限制最大高度 */ - } - - /* - * 重置按钮悬停效果 - */ - #resetBtn:hover { - background-color: #374151; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - } - - /* - * 快捷按钮样式 - * 用于快速选择常用位置 - */ - #shortcutBtn { - background-color: #1e1e2e; /* 深色背景 */ - color: #9ca3af; /* 灰色文字 */ - border: 1px solid #3a3a4a; /* 边框 */ - border-radius: 8px; /* 圆角 */ - padding: 8px 12px; /* 内边距 */ - font-size: 13px; /* 字体大小 */ - min-width: 100px; /* 最小宽度 */ - } - - /* - * 快捷按钮悬停效果 - */ - #shortcutBtn:hover { - background-color: #252538; /* 背景变亮 */ - color: #ffffff; /* 文字变白 */ - border-color: #8b5cf6; /* 品牌色边框 */ - } - - /* - * 设置复选框样式 - * 用于开关类型的设置选项 - */ - #settingsCheckbox { - color: #ffffff; /* 白色文字 */ - font-size: 14px; /* 字体大小 */ - spacing: 8px; /* 复选框与文字间距 */ - } - - /* - * 复选框指示器样式 - */ - #settingsCheckbox::indicator { - width: 18px; /* 宽度 */ - height: 18px; /* 高度 */ - border-radius: 4px; /* 圆角 */ - border: 2px solid #3a3a4a; /* 边框 */ - background-color: #1e1e2e; /* 背景色 */ - } - - /* - * 复选框选中状态 - */ - #settingsCheckbox::indicator:checked { - background-color: #8b5cf6; /* 品牌色背景 */ - border-color: #8b5cf6; /* 品牌色边框 */ - image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iOSIgdmlld0JveD0iMCAwIDEyIDkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xIDQuNUw0LjUgOEwxMSAxIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L3N2Zz4K); - } - - /* ======================================== - 导入对话框样式定义 - ======================================== */ - - /* - * 文件上传区域样式 - * 支持拖拽上传的文件放置区域 - * 使用虚线边框表示可拖拽区域 - */ - #uploadArea { - background-color: #3a3a3a; /* 深灰背景 */ - border: 2px dashed #4a4a4a; /* 虚线边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 20px; /* 内边距 */ - } - - /* - * 文件拖拽悬停状态 - * 当文件被拖拽到上传区域上方时的样式 - * 边框和背景高亮,提供清晰的视觉反馈 - */ - #uploadArea[dragOver="true"] { - border-color: #8b5cf6; /* 品牌紫色边框 */ - background-color: rgba(139, 92, 246, 0.1); /* 半透明紫色背景 */ - } - - /* - * 上传按钮样式 - * 用于手动选择文件的按钮 - * 使用品牌色突出显示 - */ - #uploadBtn { - background-color: #8b5cf6; /* 品牌紫色背景 */ - color: white; /* 白色文字 */ - border: none; /* 无边框 */ - border-radius: 6px; /* 圆角设计 */ - padding: 8px 16px; /* 内边距 */ - font-size: 14px; /* 标准字体大小 */ - } - - /* - * 上传按钮悬停效果 - * 颜色变深,增强交互反馈 - */ - #uploadBtn:hover { - background-color: #7c3aed; /* 更深的紫色 */ - } - - /* ======================================== - 通用组件样式定义 - ======================================== */ - - /* - * 分组框样式 - * 用于将相关控件分组显示的容器 - * 包含标题和边框,增强内容组织 - */ - QGroupBox { - font-weight: 600; /* 粗体标题 */ - color: #ffffff; /* 白色文字 */ - border: 1px solid #3a3a3a; /* 深灰边框 */ - border-radius: 8px; /* 圆角设计 */ - margin-top: 10px; /* 顶部外边距 */ - padding-top: 10px; /* 顶部内边距 */ - } - - /* - * 分组框标题样式 - * 分组框顶部的标题文字定位和样式 - */ - QGroupBox::title { - subcontrol-origin: margin; /* 标题定位基准 */ - left: 10px; /* 左侧偏移 */ - padding: 0 5px 0 5px; /* 左右内边距 */ - } - - /* - * 列表控件样式 - * 用于显示项目列表、文件列表等的控件 - * 采用深色主题设计 - */ - QListWidget { - background-color: #3a3a3a; /* 深灰背景 */ - border: 1px solid #4a4a4a; /* 深灰边框 */ - border-radius: 6px; /* 圆角设计 */ - padding: 5px; /* 内边距 */ - color: #ffffff; /* 白色文字 */ - } - - /* - * 列表项样式 - * 列表中每个项目的样式 - * 使用底部边框分隔各个项目 - */ - QListWidget::item { - padding: 5px; /* 内边距 */ - border-bottom: 1px solid #4a4a4a; /* 底部分隔线 */ - } - - /* - * 最后一个列表项样式 - * 移除最后一项的底部边框,避免多余的分隔线 - */ - QListWidget::item:last { - border-bottom: none; /* 无底部边框 */ - } - - /* - * 复选框样式 - * 用于选择操作的复选框控件 - * 采用自定义样式替换系统默认外观 - */ - QCheckBox { - color: #ffffff; /* 白色文字 */ - spacing: 8px; /* 复选框与文字间距 */ - } - - /* - * 复选框指示器样式 - * 复选框的方形指示器部分 - * 使用深色主题和圆角设计 - */ - QCheckBox::indicator { - width: 16px; /* 指示器宽度 */ - height: 16px; /* 指示器高度 */ - border: 2px solid #4a4a4a; /* 深灰边框 */ - border-radius: 3px; /* 小圆角 */ - background-color: #3a3a3a; /* 深灰背景 */ - } - - /* - * 复选框选中状态 - * 当复选框被选中时的样式 - * 使用品牌色背景和边框 - */ - QCheckBox::indicator:checked { - background-color: #8b5cf6; /* 品牌紫色背景 */ - border-color: #8b5cf6; /* 品牌紫色边框 */ - } - - /* - * 复选框选中标记 - * 选中状态下显示的勾选标记 - * 使用白色粗体勾号 - */ - QCheckBox::indicator:checked::after { - content: "✓"; /* 勾选标记 */ - color: white; /* 白色标记 */ - font-weight: bold; /* 粗体强调 */ - } - - /* ======================================== - 滚动条样式定义 - ======================================== */ - - /* - * 垂直滚动条样式 - * 自定义滚动条外观,替换系统默认样式 - * 采用窄宽度和圆角设计,更加现代化 - */ + /* ---------- Scrollbars ---------- */ QScrollBar:vertical { - background-color: #252538; /* 滚动条背景色 */ - width: 8px; /* 滚动条宽度 */ - border-radius: 4px; /* 圆角设计 */ + background: transparent; + width: 12px; + margin: 8px 0; } - /* - * 滚动条滑块样式 - * 用户可拖拽的滚动条滑块部分 - * 使用较亮的颜色便于识别 - */ QScrollBar::handle:vertical { - background-color: #4a4a5a; /* 滑块背景色 */ - border-radius: 4px; /* 圆角设计 */ - min-height: 20px; /* 最小高度 */ + background: #2b313f; + border-radius: 6px; + min-height: 32px; } - /* - * 滚动条滑块悬停效果 - * 当鼠标悬停在滑块上时变亮 - */ QScrollBar::handle:vertical:hover { - background-color: #6a6a7a; /* 更亮的滑块颜色 */ + background: #3a4254; } - /* - * 滚动条箭头按钮样式 - * 隐藏滚动条两端的箭头按钮,保持简洁外观 - */ QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { - height: 0px; /* 高度为0,隐藏箭头 */ + height: 0; } - /* ======================================== - 菜单样式定义 - ======================================== */ - - /* - * 右键菜单和下拉菜单样式 - * 统一的菜单外观设计,采用深色主题 - * 包含圆角和边框,增强视觉层次 - */ - QMenu { - background-color: #2a2a2a; /* 深灰背景 */ - border: 1px solid #3a3a3a; /* 深灰边框 */ - border-radius: 8px; /* 圆角设计 */ - padding: 8px 0; /* 上下内边距 */ + QScrollBar:horizontal { + background: transparent; + height: 12px; + margin: 0 8px; } - /* - * 菜单项样式 - * 菜单中每个选项的样式 - * 使用适当的内边距增强可点击性 - */ - QMenu::item { - padding: 8px 16px 8px 36px; /* 上 右 下 左,左边距36px给图标留空间 */ - color: #ffffff; /* 白色文字 */ - background-color: transparent; /* 透明背景 */ - border-radius: 4px; /* 圆角 */ - min-height: 20px; /* 最小高度 */ + QScrollBar::handle:horizontal { + background: #2b313f; + border-radius: 6px; + min-width: 32px; } - /* - * 菜单项选中状态 - * 当鼠标悬停或键盘选中菜单项时的样式 - */ - QMenu::item:selected { - background-color: #3a3a3a; /* 深灰背景高亮 */ + QScrollBar::handle:horizontal:hover { + background: #3a4254; } - /* - * 菜单图标样式 - * 调整图标位置和大小,使其与文字保持合适间距 - */ - QMenu::icon { - left: 12px; /* 图标距离左边12px */ - width: 16px; /* 图标宽度 */ - height: 16px; /* 图标高度 */ + QScrollBar::add-line:horizontal, + QScrollBar::sub-line:horizontal { + width: 0; } - /* - * 菜单分隔线样式 - * 用于分隔不同功能组的菜单项 - */ - QMenu::separator { - height: 1px; /* 分隔线高度 */ - background-color: #3a3a3a; /* 深灰色分隔线 */ - margin: 4px 0; /* 上下外边距 */ - } - - /* ======================================== - 状态栏和菜单栏样式定义 - ======================================== */ - - /* - * 应用程序底部的状态信息显示栏 - * 显示当前操作状态、进度信息等 - */ - QStatusBar { - background-color: #2a2a2a; /* 深灰背景 */ - border-top: 1px solid #3a3a3a; /* 顶部分隔线 */ - color: #cccccc; /* 浅灰色文字 */ - } - - /* - * 菜单栏样式 - * 应用程序顶部的主菜单栏 - * 包含"文件"、"编辑"、"视图"等主要菜单 - */ - QMenuBar { - background-color: #2a2a2a; /* 深灰背景 */ - color: #ffffff; /* 白色文字 */ - border-bottom: 1px solid #3a3a3a; /* 底部分隔线 */ - } - - /* - * 菜单栏项目样式 - * 菜单栏中每个主菜单项的样式 - * 如"文件"、"编辑"等菜单项 - */ - QMenuBar::item { - padding: 8px 12px; /* 内边距 */ - background-color: transparent; /* 透明背景 */ - } - - /* - * 菜单栏项目选中状态 - * 当鼠标悬停或点击菜单栏项目时的样式 - */ - QMenuBar::item:selected { - background-color: #3a3a3a; /* 深灰背景高亮 */ + QToolTip { + background-color: #1c202b; + color: #f5f6f9; + border: 1px solid #2a303d; + padding: 6px 8px; } """ @staticmethod def get_card_style(): return """ - /* 基础卡片样式 - 修复继承问题 */ #projectCard { - background-color: #8b5cf6; - border: 1px solid #5a5a6a; - border-radius: 16px; + background-color: #1b1f2a; + border: 1px solid #242a38; + border-radius: 18px; } - /* 简化悬停状态 */ #projectCard:hover { - background-color: #7c3aed; - border-color: #6a6a7a; + background-color: #212634; + border-color: #2d3343; } - /* 头部样式 - 移除透明背景 */ #projectHeader { - background-color: #8b5cf6; - border-top-left-radius: 16px; - border-top-right-radius: 16px; + background: transparent; + border-bottom: none; } #projectTitle { - font-size: 14px; + color: #f2f4f9; + font-size: 15px; font-weight: 600; - color: #ffffff; - background-color: transparent; - } - - #menuBtn { - background-color: transparent; - border: none; - border-radius: 4px; - color: #ffffff; - font-size: 16px; - } - - #menuBtn:hover { - background-color: rgba(255, 255, 255, 0.2); - } - - /* 图片区域样式 - 调整尺寸和边距 */ - #projectImageContainer { - background-color: transparent; - padding: 0px; /* 减少内边距 */ } #projectImage { - background-color: #3a3a4a; - border-radius: 12px; - min-height: 100px; /* 减小最小高度 */ - max-height: 120px; + background-color: #292f3d; + border-radius: 5px; + min-height: 140px; } - #projectIcon { - font-size: 36px; /* 减小图标大小 */ - color: #ffffff; - padding: 10px; - } - - /* 底部样式 - 移除透明背景 */ #projectFooter { - background-color: #8b5cf6; - border-bottom-left-radius: 16px; - border-bottom-right-radius: 16px; + background: transparent; + border-top: 1px solid #232838; + margin-top: 12px; + padding-top: 12px; } #projectDate { - font-size: 11px; - color: #e0e0ff; /* 更亮的颜色提高可读性 */ - font-weight: 400; - background-color: transparent; + color: #9aa1b3; + font-size: 12px; } - """ + """ diff --git a/data/projects.json b/data/projects.json index e4939e6..64910f0 100644 --- a/data/projects.json +++ b/data/projects.json @@ -1,10 +1,21 @@ [ { - "id": 6, - "title": "XNWX", - "date": "2025-10-11 12:15:15", + "id": 2, + "title": "ab", + "date": "2025-10-14 18:23:06", "type": "imported", - "image": "C:\\Users\\29381\\Desktop\\XNWX\\XNWX.png", + "image": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\Resources\\ProjectPreviews\\default_preview_2.png", + "path": "C:\\Users\\29381\\Desktop", + "project_dir": "C:\\Users\\29381\\Desktop\\ab", + "description": "从文件夹 ab 导入", + "status": "normal" + }, + { + "id": 1, + "title": "XNWX", + "date": "2025-10-14 18:05:51", + "type": "imported", + "image": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\Resources\\ProjectPreviews\\preview_1_1760491477496.png", "path": "C:\\Users\\29381\\Desktop", "project_dir": "C:\\Users\\29381\\Desktop\\XNWX", "description": "从文件夹 XNWX 导入",