From c9aa04fa7311f94473d2e0d722431a32d636e6e6 Mon Sep 17 00:00:00 2001 From: zcwBit Date: Mon, 4 Aug 2025 16:12:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A7=84=E7=A8=8B=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=20=E6=8F=90=E4=BE=9B=E6=95=B4=E8=A1=8Chover?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Static/Procedure.qss | 2209 +++----------------- Static/ProcedureTable.qss | 249 +++ Static/StepExecutor.qss | 390 ++++ UI/ProcedureManager/ProcedureManager.py | 422 ++-- UI/ProcedureManager/StepExecutor.py | 297 ++- model/ProcedureModel/ProcedureProcessor.py | 201 -- 6 files changed, 1335 insertions(+), 2433 deletions(-) create mode 100644 Static/ProcedureTable.qss create mode 100644 Static/StepExecutor.qss diff --git a/Static/Procedure.qss b/Static/Procedure.qss index f93afdd..8c3a3e5 100644 --- a/Static/Procedure.qss +++ b/Static/Procedure.qss @@ -1,42 +1,22 @@ -/* ==================== DCS2025 规程管理界面样式 - 现代化设计 ==================== */ +/* ==================== DCS2025 规程管理界面样式 ==================== */ /* ==================== 全局样式 ==================== */ QWidget { background-color: #F8FAFC; color: #1F2937; - font-family: "PingFangSC-Medium", "Microsoft YaHei", "Segoe UI", Arial, sans-serif; + font-family: "Microsoft YaHei", sans-serif; font-size: 14px; - selection-background-color: #3B82F6; - selection-color: #FFFFFF; } -/* ==================== 主窗口样式 ==================== */ QMainWindow { background-color: #F5F7FA; border: none; } -/* ==================== 工具栏样式 ==================== */ -QToolBar { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FFFFFF, stop:1 #F8FAFC); - border: none; - border-bottom: 1px solid #E5E7EB; - spacing: 12px; - padding: 16px 24px; - font-size: 13px; - font-weight: 500; -} - -QToolBar::separator { - background-color: #E5E7EB; - width: 1px; - margin: 8px 6px; -} +/* ==================== 规程管理按钮样式 - 参考变量管理界面 ==================== */ -/* ==================== 工具栏按钮样式 - 与变量表按钮一致 ==================== */ -/* 工具栏按钮基础样式 */ -QToolBar QToolButton { +/* 导入规程按钮 - 绿色主题 */ +QPushButton#importToolBtn { color: #047857; font-size: 15px; font-weight: 600; @@ -44,2003 +24,478 @@ QToolBar QToolButton { background-color: #ECFDF5; border-radius: 6px; border: 1px solid #BBF7D0; - margin: 2px; - min-width: 80px; - min-height: 32px; font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QToolBar QToolButton:hover { +QPushButton#importToolBtn:hover { background-color: #D1FAE5; border-color: #86EFAC; color: #065F46; } -QToolBar QToolButton:pressed { +QPushButton#importToolBtn:pressed { background-color: #A7F3D0; border-color: #6EE7B7; color: #064E3B; } -QToolBar QToolButton:disabled { - background-color: #F9FAFB; - color: #9CA3AF; - border-color: #E5E7EB; +/* 添加分类按钮 - 蓝色主题 */ +QPushButton#addCategoryToolBtn { + color: #1D4ED8; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #EBF8FF; + border-radius: 6px; + border: 1px solid #BFDBFE; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -/* ==================== 标签页样式 ==================== */ -QTabWidget::pane { - border: 1px solid #E5E7EB; - border-radius: 12px; - background-color: #FFFFFF; - margin-top: -1px; +QPushButton#addCategoryToolBtn:hover { + background-color: #DBEAFE; + border-color: #93C5FD; + color: #1E40AF; } -QTabWidget::tab-bar { - alignment: left; +QPushButton#addCategoryToolBtn:pressed { + background-color: #BFDBFE; + border-color: #60A5FA; + color: #1E3A8A; } -QTabBar::tab { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F9FAFB, stop:1 #F3F4F6); - border: 1px solid #E5E7EB; - border-bottom: none; - border-top-left-radius: 12px; - border-top-right-radius: 12px; - padding: 16px 24px; - margin-right: 4px; - color: #6B7280; - font-size: 14px; - font-weight: 500; - min-width: 140px; +/* 删除分类按钮 - 红色主题 */ +QPushButton#deleteCategoryToolBtn { + color: #B91C1C; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF2F2; + border-radius: 6px; + border: 1px solid #FECACA; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QTabBar::tab:selected { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FFFFFF, stop:1 #F8FAFC); - color: #1976D2; - border-color: #E5E7EB; +QPushButton#deleteCategoryToolBtn:hover { + background-color: #FEE2E2; + border-color: #FCA5A5; + color: #991B1B; +} + +QPushButton#deleteCategoryToolBtn:pressed { + background-color: #FECACA; + border-color: #F87171; + color: #7F1D1D; +} + +/* 打开规程按钮 - 蓝色主题 */ +QPushButton#openProcedureToolBtn { + color: #1D4ED8; + font-size: 15px; font-weight: 600; + padding: 8px 16px; + background-color: #EBF8FF; + border-radius: 6px; + border: 1px solid #BFDBFE; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QTabBar::tab:hover:!selected { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FFFFFF, stop:1 #F9FAFB); - color: #374151; +QPushButton#openProcedureToolBtn:hover { + background-color: #DBEAFE; + border-color: #93C5FD; + color: #1E40AF; } -/* 关闭按钮 */ -QTabBar::close-button { - image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDRMNCA4TDEyIDEyIiBzdHJva2U9IiM2QjcyODAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=); - subcontrol-position: right; - subcontrol-origin: padding; - border-radius: 4px; - margin: 6px; - padding: 2px; +QPushButton#openProcedureToolBtn:pressed { + background-color: #BFDBFE; + border-color: #60A5FA; + color: #1E3A8A; } -QTabBar::close-button:hover { - background-color: #FEE2E2; +/* 删除规程按钮 - 红色主题 */ +QPushButton#deleteProcedureToolBtn { + color: #B91C1C; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF2F2; + border-radius: 6px; border: 1px solid #FECACA; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -/* ==================== 卡片式容器样式 ==================== */ -/* 分类列表卡片 */ -QWidget#categoryCard { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - margin: 8px; +QPushButton#deleteProcedureToolBtn:hover { + background-color: #FEE2E2; + border-color: #FCA5A5; + color: #991B1B; } -/* 规程列表卡片 */ -QWidget#procedureCard { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - margin: 8px; +QPushButton#deleteProcedureToolBtn:pressed { + background-color: #FECACA; + border-color: #F87171; + color: #7F1D1D; } -/* 卡片标题 */ -QLabel#cardTitle { - font-size: 16px; +/* 历史记录按钮 - 紫色主题 */ +QPushButton#historyToolBtn { + color: #7C3AED; + font-size: 15px; font-weight: 600; - color: #1F2937; - padding: 0 0 12px 0; - border-bottom: 2px solid #E5E7EB; - margin-bottom: 16px; + padding: 8px 16px; + background-color: #F3E8FF; + border-radius: 6px; + border: 1px solid #C4B5FD; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -/* ==================== 列表控件样式 ==================== */ -/* 分类列表 */ -QListWidget#categoryList { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 8px; - outline: none; - font-size: 14px; +QPushButton#historyToolBtn:hover { + background-color: #EDE9FE; + border-color: #A78BFA; + color: #6D28D9; } -QListWidget#categoryList::item { - background-color: transparent; - border: none; - border-radius: 6px; - padding: 12px 16px; - margin: 2px 0; - color: #374151; - font-weight: 500; +QPushButton#historyToolBtn:pressed { + background-color: #DDD6FE; + border-color: #8B5CF6; + color: #5B21B6; } -QListWidget#categoryList::item:hover { - background-color: #F3F4F6; - color: #1F2937; +/* 批量执行按钮 - 绿色主题 */ +QPushButton#batchExecuteToolBtn { + color: #047857; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #ECFDF5; + border-radius: 6px; + border: 1px solid #BBF7D0; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QListWidget#categoryList::item:selected { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #3B82F6, stop:1 #2563EB); - color: #FFFFFF; - font-weight: 600; +QPushButton#batchExecuteToolBtn:hover { + background-color: #D1FAE5; + border-color: #86EFAC; + color: #065F46; } -/* 规程列表 */ -QListWidget#procedureList { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 8px; - outline: none; - font-size: 14px; +QPushButton#batchExecuteToolBtn:pressed { + background-color: #A7F3D0; + border-color: #6EE7B7; + color: #064E3B; } -QListWidget#procedureList::item { - background-color: transparent; - border: none; +/* 关键词管理按钮 - 紫色主题 */ +QPushButton#keywordManageToolBtn { + color: #7C3AED; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #F3E8FF; border-radius: 6px; - padding: 16px 20px; - margin: 3px 0; - color: #374151; - font-weight: 500; - min-height: 20px; + border: 1px solid #C4B5FD; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QListWidget#procedureList::item:hover { - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - color: #1F2937; +QPushButton#keywordManageToolBtn:hover { + background-color: #EDE9FE; + border-color: #A78BFA; + color: #6D28D9; } -QListWidget#procedureList::item:selected { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #EBF8FF, stop:1 #DBEAFE); - border: 1px solid #93C5FD; - color: #1E40AF; - font-weight: 600; +QPushButton#keywordManageToolBtn:pressed { + background-color: #DDD6FE; + border-color: #8B5CF6; + color: #5B21B6; } -/* ==================== 按钮样式 ==================== */ -/* 基础按钮样式 */ -QPushButton { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 12px 20px; - font-weight: 500; - color: #374151; - font-size: 14px; - min-width: 100px; - min-height: 36px; +/* 导出规程按钮 - 橙色主题 */ +QPushButton#exportProcedureToolBtn { + color: #D97706; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF3C7; + border-radius: 6px; + border: 1px solid #FCD34D; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + /* min-width: 85px; + min-height: 36px; */ } -QPushButton:hover { - background-color: #F9FAFB; - border-color: #D1D5DB; - color: #1F2937; +QPushButton#exportProcedureToolBtn:hover { + background-color: #FDE68A; + border-color: #FBBF24; + color: #B45309; } -QPushButton:pressed { - background-color: #F3F4F6; - border-color: #9CA3AF; - color: #111827; +QPushButton#exportProcedureToolBtn:pressed { + background-color: #FCD34D; + border-color: #F59E0B; + color: #92400E; } -QPushButton:disabled { - background-color: #F9FAFB; +/* 禁用状态 */ +QPushButton#importToolBtn:disabled, +QPushButton#addCategoryToolBtn:disabled, +QPushButton#deleteCategoryToolBtn:disabled, +QPushButton#openProcedureToolBtn:disabled, +QPushButton#deleteProcedureToolBtn:disabled, +QPushButton#historyToolBtn:disabled, +QPushButton#batchExecuteToolBtn:disabled, +QPushButton#keywordManageToolBtn:disabled, +QPushButton#exportProcedureToolBtn:disabled { + background-color: #F3F4F6; color: #9CA3AF; border-color: #E5E7EB; } -/* 主要操作按钮 - 蓝色 */ -QPushButton#primaryBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border: 1px solid #2563EB; - color: #FFFFFF; +/* ==================== 规程管理界面其他按钮样式 ==================== */ + +/* 添加分类按钮 - 蓝色主题 (在分类操作区域) */ +QPushButton#addCategoryBtn { + color: #1D4ED8; + font-size: 15px; font-weight: 600; + padding: 8px 16px; + background-color: #EBF8FF; + border-radius: 6px; + border: 1px solid #BFDBFE; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QPushButton#primaryBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); - border-color: #1D4ED8; +QPushButton#addCategoryBtn:hover { + background-color: #DBEAFE; + border-color: #93C5FD; + color: #1E40AF; } -QPushButton#primaryBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); - border-color: #1E40AF; +QPushButton#addCategoryBtn:pressed { + background-color: #BFDBFE; + border-color: #60A5FA; + color: #1E3A8A; } -/* 成功操作按钮 - 绿色 */ -QPushButton#successBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #10B981, stop:1 #059669); - border: 1px solid #059669; - color: #FFFFFF; +/* 删除分类按钮 - 红色主题 (在分类操作区域) */ +QPushButton#deleteCategoryBtn { + color: #B91C1C; + font-size: 15px; font-weight: 600; + padding: 8px 16px; + background-color: #FEF2F2; + border-radius: 6px; + border: 1px solid #FECACA; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QPushButton#successBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #059669, stop:1 #047857); - border-color: #047857; +QPushButton#deleteCategoryBtn:hover { + background-color: #FEE2E2; + border-color: #FCA5A5; + color: #991B1B; } -QPushButton#successBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #047857, stop:1 #065F46); - border-color: #065F46; +QPushButton#deleteCategoryBtn:pressed { + background-color: #FECACA; + border-color: #F87171; + color: #7F1D1D; } -/* 警告操作按钮 - 橙色 */ -QPushButton#warningBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F59E0B, stop:1 #D97706); - border: 1px solid #D97706; - color: #FFFFFF; +/* 导入规程按钮 - 绿色主题 (在规程操作区域) */ +QPushButton#importBtn { + color: #047857; + font-size: 15px; font-weight: 600; + padding: 8px 16px; + background-color: #ECFDF5; + border-radius: 6px; + border: 1px solid #BBF7D0; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QPushButton#warningBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #D97706, stop:1 #B45309); - border-color: #B45309; +QPushButton#importBtn:hover { + background-color: #D1FAE5; + border-color: #86EFAC; + color: #065F46; } -QPushButton#warningBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B45309, stop:1 #92400E); - border-color: #92400E; +QPushButton#importBtn:pressed { + background-color: #A7F3D0; + border-color: #6EE7B7; + color: #064E3B; } -/* 危险操作按钮 - 红色 */ -QPushButton#dangerBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #EF4444, stop:1 #DC2626); - border: 1px solid #DC2626; - color: #FFFFFF; +/* 打开规程按钮 - 蓝色主题 (在规程操作区域) */ +QPushButton#openBtn { + color: #1D4ED8; + font-size: 15px; font-weight: 600; + padding: 8px 16px; + background-color: #EBF8FF; + border-radius: 6px; + border: 1px solid #BFDBFE; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QPushButton#dangerBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #DC2626, stop:1 #B91C1C); - border-color: #B91C1C; -} - -QPushButton#dangerBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B91C1C, stop:1 #991B1B); - border-color: #991B1B; +QPushButton#openBtn:hover { + background-color: #DBEAFE; + border-color: #93C5FD; + color: #1E40AF; } -/* ==================== 表格样式 ==================== */ -QTableWidget { - background-color: #FFFFFF; - alternate-background-color: #F8FAFC; - gridline-color: #E5E7EB; - border: 1px solid #E5E7EB; - border-radius: 8px; - selection-background-color: #EBF8FF; - selection-color: #1E40AF; - outline: none; - font-size: 13px; +QPushButton#openBtn:pressed { + background-color: #BFDBFE; + border-color: #60A5FA; + color: #1E3A8A; } -QTableWidget::item { - padding: 12px 16px; - border: none; - background-color: transparent; +/* 导出规程按钮 - 橙色主题 (在规程操作区域) */ +QPushButton#exportBtn { + color: #D97706; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF3C7; + border-radius: 6px; + border: 1px solid #FCD34D; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QTableWidget::item:selected { - background-color: #EBF8FF; - color: #1E40AF; +QPushButton#exportBtn:hover { + background-color: #FDE68A; + border-color: #FBBF24; + color: #B45309; } -QTableWidget::item:hover { - background-color: #F8FAFC; +QPushButton#exportBtn:pressed { + background-color: #FCD34D; + border-color: #F59E0B; + color: #92400E; } -/* 表头样式 */ -QHeaderView::section { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F9FAFB, stop:1 #F3F4F6); - color: #374151; - padding: 16px 12px; - border: none; - border-right: 1px solid #E5E7EB; - border-bottom: 2px solid #E5E7EB; +/* 删除规程按钮 - 红色主题 (在规程操作区域) */ +QPushButton#deleteBtn { + color: #B91C1C; + font-size: 15px; font-weight: 600; - font-size: 13px; - text-align: center; + padding: 8px 16px; + background-color: #FEF2F2; + border-radius: 6px; + border: 1px solid #FECACA; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 80px; + min-height: 32px; } -QHeaderView::section:first { - border-top-left-radius: 8px; +QPushButton#deleteBtn:hover { + background-color: #FEE2E2; + border-color: #FCA5A5; + color: #991B1B; } -QHeaderView::section:last { - border-top-right-radius: 8px; - border-right: none; +QPushButton#deleteBtn:pressed { + background-color: #FECACA; + border-color: #F87171; + color: #7F1D1D; } -QHeaderView::section:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F3F4F6, stop:1 #E5E7EB); -} +/* ==================== 其他基础组件样式 ==================== */ -/* ==================== 输入控件样式 ==================== */ -QLineEdit { +/* 列表控件 */ +QListWidget { background-color: #FFFFFF; - border: 2px solid #E5E7EB; + border: 1px solid #E5E7EB; border-radius: 8px; - padding: 4px 8px; - color: #374151; - font-size: 14px; - font-weight: 400; + padding: 4px; } -QLineEdit:focus { - border-color: #3B82F6; - background-color: #FEFEFF; - outline: none; +QListWidget::item { + padding: 8px 12px; + border-radius: 6px; + margin: 2px 0; } -QLineEdit:hover { - border-color: #9CA3AF; +QListWidget::item:hover { + background-color: #F3F4F6; } -/* 规程编辑器中的小型输入框 */ -QLineEdit#procedureNameEdit, -QLineEdit#procedureNumberEdit, -QLineEdit#procedureTypeEdit, -QLineEdit#procedureDescriptionEdit { - padding: 4px 8px; - font-size: 12px; - font-family: "Microsoft YaHei", "PingFangSC-Regular", sans-serif; - border: 1px solid #E5E7EB; - border-radius: 4px; - min-height: 22px; - line-height: 1.3; - color: #374151; +QListWidget::item:selected { + background-color: #EBF8FF; + color: #1E40AF; } -QLineEdit#procedureNameEdit:focus, -QLineEdit#procedureNumberEdit:focus, -QLineEdit#procedureTypeEdit:focus, -QLineEdit#procedureDescriptionEdit:focus { - border-color: #3B82F6; - background-color: #FEFEFF; -} +/* 按钮 */ -QTextEdit { - background-color: #FFFFFF; - border: 2px solid #E5E7EB; - border-radius: 8px; - /* padding: 16px; */ - color: #374151; - font-size: 14px; - line-height: 1.5; -} - -QTextEdit:focus { - border-color: #3B82F6; - background-color: #FEFEFF; - outline: none; -} - -/* ==================== 组合框样式 ==================== */ -QComboBox { - background-color: #FFFFFF; - border: 2px solid #E5E7EB; - border-radius: 8px; - padding: 12px 16px; - color: #374151; - font-size: 14px; - min-width: 120px; -} - -QComboBox:focus { - border-color: #3B82F6; - background-color: #FEFEFF; -} - -QComboBox::drop-down { - border: none; - width: 32px; -} - -QComboBox::down-arrow { - image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQgNkw4IDEwTDEyIDYiIHN0cm9rZT0iIzM3NDE1MSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+); - width: 16px; - height: 16px; -} -QComboBox QAbstractItemView { +/* 输入框 */ +QLineEdit { background-color: #FFFFFF; border: 1px solid #E5E7EB; - border-radius: 8px; - color: #374151; - selection-background-color: #EBF8FF; - selection-color: #1E40AF; - padding: 4px; -} - -QComboBox QAbstractItemView::item { - height: 36px; - padding: 8px 16px; - border: none; border-radius: 6px; -} - -QComboBox QAbstractItemView::item:hover { - background-color: #F8FAFC; -} - -QComboBox QAbstractItemView::item:selected { - background-color: #EBF8FF; - color: #1E40AF; -} - -/* ==================== 复选框样式 ==================== */ -QCheckBox { + padding: 8px 12px; color: #374151; - spacing: 12px; - font-size: 14px; -} - -QCheckBox::indicator { - width: 20px; - height: 20px; - border: 2px solid #E5E7EB; - border-radius: 4px; - background-color: #FFFFFF; } -QCheckBox::indicator:hover { +QLineEdit:focus { border-color: #3B82F6; - background-color: #F8FAFC; -} - -QCheckBox::indicator:checked { - background-color: #3B82F6; - border-color: #2563EB; - image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEzIDRMNiAxMUwzIDgiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+); -} - -QCheckBox::indicator:checked:hover { - background-color: #2563EB; -} - -/* ==================== 进度条样式 ==================== */ -QProgressBar { - background-color: #F3F4F6; - border: 1px solid #E5E7EB; - border-radius: 8px; - text-align: center; - color: #374151; - font-weight: 600; - font-size: 13px; - height: 24px; -} - -QProgressBar::chunk { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #3B82F6, stop:1 #2563EB); - border-radius: 7px; - margin: 1px; -} - -/* ==================== 滚动条样式 ==================== */ -QScrollBar:vertical { - background-color: #F9FAFB; - width: 12px; - border-radius: 6px; - margin: 0px; -} - -QScrollBar::handle:vertical { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #E5E7EB, stop:1 #D1D5DB); - border-radius: 6px; - min-height: 30px; -} - -QScrollBar::handle:vertical:hover { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #3B82F6, stop:1 #2563EB); -} - -QScrollBar::handle:vertical:pressed { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #2563EB, stop:1 #1D4ED8); -} - -QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { - height: 0px; - background: none; -} - -QScrollBar:horizontal { - background-color: #F9FAFB; - height: 12px; - border-radius: 6px; - margin: 0px; -} - -QScrollBar::handle:horizontal { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #E5E7EB, stop:1 #D1D5DB); - border-radius: 6px; - min-width: 30px; -} - -QScrollBar::handle:horizontal:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); -} - -QScrollBar::handle:horizontal:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); -} - -QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { - width: 0px; - background: none; -} - -/* ==================== 菜单样式 ==================== */ -QMenu { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 8px; - color: #374151; -} - -QMenu::item { - background-color: transparent; - padding: 12px 16px; - border-radius: 6px; - margin: 2px; - font-size: 14px; -} - -QMenu::item:selected { - background-color: #EBF8FF; - color: #1E40AF; -} - -QMenu::item:disabled { - color: #9CA3AF; -} - -QMenu::separator { - height: 1px; - background-color: #E5E7EB; - margin: 8px 12px; -} - -/* ==================== 状态栏样式 ==================== */ -QStatusBar { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F9FAFB, stop:1 #F3F4F6); - border-top: 1px solid #E5E7EB; - color: #6B7280; - padding: 8px 16px; - font-size: 13px; -} - -QStatusBar::item { - border: none; -} - -/* ==================== 对话框样式 ==================== */ -QDialog { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; -} - -QDialogButtonBox QPushButton { - min-width: 100px; - padding: 12px 24px; -} - -/* ==================== 消息框样式 ==================== */ -QMessageBox { - background-color: #FFFFFF; - color: #374151; - border-radius: 12px; -} - -QMessageBox QLabel { - color: #374151; - font-size: 14px; -} - -QMessageBox QPushButton { - min-width: 80px; - padding: 10px 20px; -} - -/* ==================== 工具提示样式 ==================== */ -QToolTip { - background-color: #1F2937; - color: #F9FAFB; - border: 1px solid #374151; - border-radius: 6px; - padding: 8px 12px; - font-size: 13px; - opacity: 240; -} - -/* ==================== 分割器样式 ==================== */ -QSplitter::handle { - background-color: #E5E7EB; -} - -QSplitter::handle:horizontal { - width: 2px; - border-radius: 1px; -} - -QSplitter::handle:vertical { - height: 2px; - border-radius: 1px; -} - -QSplitter::handle:hover { - background-color: #3B82F6; -} - -/* ==================== 特殊状态样式 ==================== */ -/* 成功状态 */ -.status-success { - color: #059669; - font-weight: 600; -} - -/* 错误状态 */ -.status-error { - color: #DC2626; - font-weight: 600; -} - -/* 警告状态 */ -.status-warning { - color: #D97706; - font-weight: 600; -} - -/* 信息状态 */ -.status-info { - color: #2563EB; - font-weight: 600; -} - -/* ==================== 规程执行界面特殊样式 ==================== */ -/* 规程信息卡片 */ -QWidget#procedureInfoCard { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 24px; - margin: 12px; -} - -/* 信息组标题 */ -QLabel#infoGroupTitle { - font-size: 14px; - font-weight: 600; - color: #6B7280; - margin-bottom: 8px; -} - -/* 信息组值 */ -QLabel#infoGroupValue { - font-size: 16px; - font-weight: 600; - color: #1F2937; - padding: 12px 16px; - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - border-radius: 8px; - min-height: 20px; + outline: none; } -/* 步骤表格特殊样式 */ -QTableWidget#stepsTable { - background-color: #FFFFFF; +/* 标签页 */ +QTabWidget::pane { border: 1px solid #E5E7EB; border-radius: 8px; - gridline-color: #F3F4F6; -} - -QTableWidget#stepsTable::item { - padding: 16px 12px; - border: none; - background-color: transparent; - font-size: 13px; -} - -QTableWidget#stepsTable::item:selected { - background-color: #EBF8FF; - color: #1E40AF; -} - -QTableWidget#stepsTable::item:hover { - background-color: #F8FAFC; -} - -/* 主步骤样式 */ -QTableWidget#stepsTable::item[main_step="true"] { - background-color: #F0F9FF; - font-weight: 600; - color: #0C4A6E; -} - -/* 子步骤样式 */ -QTableWidget#stepsTable::item[sub_step="true"] { - background-color: #FEFEFE; - color: #374151; -} - -/* 执行成功的步骤 */ -QTableWidget#stepsTable::item[success="true"] { - background-color: rgba(16, 185, 129, 0.1); - color: #059669; -} - -/* 执行失败的步骤 */ -QTableWidget#stepsTable::item[success="false"] { - background-color: rgba(239, 68, 68, 0.1); - color: #DC2626; -} -/* ===== -=============== 规程执行界面特殊样式 ==================== */ -/* 规程信息网格布局 */ -QWidget#procedureInfoGrid { background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 24px; - margin: 12px; } -/* 信息项容器 */ -QWidget#infoItem { - background-color: #F8FAFC; +QTabBar::tab { + background-color: #F9FAFB; border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 16px; - margin: 8px; -} - -/* 信息项标题 */ -QLabel#infoItemTitle { - font-size: 12px; - font-weight: 600; + border-bottom: none; + border-radius: 8px 8px 0 0; + padding: 12px 20px; + margin-right: 2px; color: #6B7280; - margin-bottom: 8px; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -/* 信息项值 */ -QLabel#infoItemValue { - font-size: 16px; - font-weight: 600; - color: #1F2937; - padding: 8px 0; - word-wrap: break-word; } -/* 执行控制面板 */ -QWidget#executionControlPanel { +QTabBar::tab:selected { background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - margin: 12px; -} - -/* 状态指示器 */ -QLabel#executionStatus { - font-size: 14px; + color: #1976D2; font-weight: 600; - padding: 8px 16px; - border-radius: 20px; - text-align: center; -} - -/* 状态指示器 - 就绪 */ -QLabel#executionStatus[status="ready"] { - background-color: #F3F4F6; - color: #374151; - border: 1px solid #D1D5DB; -} - -/* 状态指示器 - 运行中 */ -QLabel#executionStatus[status="running"] { - background-color: #ECFDF5; - color: #166534; - border: 1px solid #BBF7D0; -} - -/* 状态指示器 - 暂停 */ -QLabel#executionStatus[status="paused"] { - background-color: #FEF3C7; - color: #92400E; - border: 1px solid #FCD34D; -} - -/* 状态指示器 - 完成 */ -QLabel#executionStatus[status="completed"] { - background-color: #EBF8FF; - color: #1E40AF; - border: 1px solid #BFDBFE; -} - -/* 状态指示器 - 错误 */ -QLabel#executionStatus[status="error"] { - background-color: #FEF2F2; - color: #991B1B; - border: 1px solid #FECACA; } -/* 进度指示器 */ -QWidget#progressIndicator { - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 16px; - margin: 8px 0; -} - -/* 进度标签 */ -QLabel#progressLabel { - font-size: 14px; - font-weight: 500; - color: #374151; - margin-bottom: 8px; -} - -/* 自定义进度条 */ -QProgressBar#executionProgress { +QTabBar::tab:hover:!selected { background-color: #F3F4F6; - border: 1px solid #E5E7EB; - border-radius: 10px; - text-align: center; color: #374151; - font-weight: 600; - font-size: 12px; - height: 20px; } -QProgressBar#executionProgress::chunk { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 #10B981, stop:1 #059669); - border-radius: 9px; - margin: 1px; -} - -/* 时间显示 */ -QLabel#timeDisplay { - font-size: 18px; - font-weight: 700; - color: #1F2937; - font-family: "Consolas", "Monaco", monospace; - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 12px 16px; - text-align: center; -} - -/* 时间显示 - 警告状态 */ -QLabel#timeDisplay[warning="true"] { - color: #D97706; - background-color: #FEF3C7; - border-color: #FCD34D; -} - -/* 时间显示 - 危险状态 */ -QLabel#timeDisplay[danger="true"] { - color: #DC2626; - background-color: #FEF2F2; - border-color: #FECACA; -} - -/* 步骤详情面板 */ -QWidget#stepDetailPanel { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - margin: 12px; -} - -/* 步骤详情标题 */ -QLabel#stepDetailTitle { - font-size: 16px; - font-weight: 600; - color: #1F2937; - margin-bottom: 16px; - padding-bottom: 8px; - border-bottom: 2px solid #E5E7EB; -} - -/* 步骤描述 */ -QLabel#stepDescription { - font-size: 14px; - color: #374151; - line-height: 1.6; - padding: 12px 16px; - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - border-radius: 8px; - word-wrap: break-word; -} - -/* 执行日志 */ -QTextEdit#executionLog { - background-color: #1F2937; - color: #F9FAFB; - border: 1px solid #374151; - border-radius: 8px; - font-family: "Consolas", "Monaco", "Courier New", monospace; - font-size: 12px; - padding: 12px; - line-height: 1.4; -} - -/* 日志滚动条 */ -QTextEdit#executionLog QScrollBar:vertical { - background-color: #374151; - width: 12px; - border-radius: 6px; -} - -QTextEdit#executionLog QScrollBar::handle:vertical { - background-color: #6B7280; - border-radius: 6px; - min-height: 30px; -} - -QTextEdit#executionLog QScrollBar::handle:vertical:hover { - background-color: #9CA3AF; -} - -/* 操作历史表格 */ -QTableWidget#operationHistory { - background-color: #FFFFFF; - alternate-background-color: #F8FAFC; - gridline-color: #F3F4F6; - border: 1px solid #E5E7EB; - border-radius: 8px; - selection-background-color: #EBF8FF; - selection-color: #1E40AF; - outline: none; - font-size: 13px; -} - -QTableWidget#operationHistory::item { - padding: 12px 16px; - border: none; - background-color: transparent; -} - -QTableWidget#operationHistory::item:selected { - background-color: #EBF8FF; - color: #1E40AF; -} - -QTableWidget#operationHistory::item:hover { - background-color: #F8FAFC; -} - -/* 操作历史表头 */ -QTableWidget#operationHistory QHeaderView::section { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F9FAFB, stop:1 #F3F4F6); - color: #374151; - padding: 16px 12px; - border: none; - border-right: 1px solid #E5E7EB; - border-bottom: 2px solid #E5E7EB; - font-weight: 600; - font-size: 13px; - text-align: center; -} - -/* 快捷操作面板 */ -QWidget#quickActionPanel { - background-color: #F8FAFC; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 16px; - margin: 8px 0; -} - -/* 快捷操作标题 */ -QLabel#quickActionTitle { - font-size: 14px; - font-weight: 600; - color: #374151; - margin-bottom: 12px; -} - -/* 快捷操作按钮组 */ -QWidget#quickActionButtons { - background-color: transparent; -} - -/* 小型按钮样式 */ -QPushButton#smallBtn { - padding: 8px 12px; - font-size: 12px; - min-width: 60px; - min-height: 28px; - border-radius: 6px; -} - -/* 图标按钮样式 */ -QPushButton#iconBtn { - padding: 10px; - min-width: 40px; - min-height: 40px; - border-radius: 8px; - font-size: 16px; -} - -QPushButton#iconBtn:hover { - transform: scale(1.05); -} - -/* 浮动操作按钮 */ -QPushButton#fabBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border: none; - border-radius: 28px; - color: #FFFFFF; - font-size: 18px; - font-weight: 600; - min-width: 56px; - min-height: 56px; - padding: 0; -} - -QPushButton#fabBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); -} - -QPushButton#fabBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); -} - -/* 通知横幅 */ -QWidget#notificationBanner { - background-color: #EBF8FF; - border: 1px solid #93C5FD; - border-radius: 8px; - padding: 12px 16px; - margin: 8px 0; -} - -/* 通知横幅 - 成功 */ -QWidget#notificationBanner[type="success"] { - background-color: #ECFDF5; - border-color: #BBF7D0; -} - -/* 通知横幅 - 警告 */ -QWidget#notificationBanner[type="warning"] { - background-color: #FEF3C7; - border-color: #FCD34D; -} - -/* 通知横幅 - 错误 */ -QWidget#notificationBanner[type="error"] { - background-color: #FEF2F2; - border-color: #FECACA; -} - -/* 通知文本 */ -QLabel#notificationText { - font-size: 14px; - font-weight: 500; - color: #374151; -} - -/* 通知文本 - 成功 */ -QLabel#notificationText[type="success"] { - color: #166534; -} - -/* 通知文本 - 警告 */ -QLabel#notificationText[type="warning"] { - color: #92400E; -} - -/* 通知文本 - 错误 */ -QLabel#notificationText[type="error"] { - color: #991B1B; -} - -/* 数据统计卡片 */ -QWidget#statsCard { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - margin: 8px; - min-width: 200px; -} - -/* 统计数值 */ -QLabel#statsValue { - font-size: 32px; - font-weight: 700; - color: #1F2937; - text-align: center; -} - -/* 统计标签 */ -QLabel#statsLabel { - font-size: 14px; - font-weight: 500; - color: #6B7280; - text-align: center; - margin-top: 8px; -} - -/* 统计变化指示器 */ -QLabel#statsChange { - font-size: 12px; - font-weight: 600; - padding: 4px 8px; - border-radius: 12px; - text-align: center; - margin-top: 8px; -} - -/* 统计变化 - 上升 */ -QLabel#statsChange[trend="up"] { - background-color: #ECFDF5; - color: #166534; -} - -/* 统计变化 - 下降 */ -QLabel#statsChange[trend="down"] { - background-color: #FEF2F2; - color: #991B1B; -} - -/* 统计变化 - 持平 */ -QLabel#statsChange[trend="stable"] { - background-color: #F3F4F6; +/* 状态栏 */ +QStatusBar { + background-color: #F9FAFB; + border-top: 1px solid #E5E7EB; color: #6B7280; -} - -/* ==================== 规程编辑器专用样式 ==================== */ -/* 基本信息标题 */ -QLabel#basicInfoTitle { - font-size: 12px; - font-weight: bold; - color: #606266; -} - -/* 步骤列表标题 */ -QLabel#stepsTitle { - font-size: 12px; - font-weight: bold; - color: #606266; -} - -/* 字段标签样式 */ -QLabel[fieldLabel="true"] { - font-size: 11px; - font-weight: bold; - color: #909399; -} - -/* 添加步骤按钮 */ -QPushButton#addStepButton { - font-size: 11px; - padding: 4px 8px; - background-color: #10B981; - color: white; - border: none; - border-radius: 4px; - font-weight: 600; -} - -QPushButton#addStepButton:hover { - background-color: #059669; -} - -QPushButton#addStepButton:pressed { - background-color: #047857; -} - -/* 删除步骤按钮 */ -QPushButton#deleteStepButton { - font-size: 11px; padding: 4px 8px; - background-color: #EF4444; - color: white; - border: none; - border-radius: 4px; - font-weight: 600; -} - -QPushButton#deleteStepButton:hover { - background-color: #DC2626; -} - -QPushButton#deleteStepButton:pressed { - background-color: #B91C1C; -} - -/* 保存规程按钮 */ -QPushButton#saveProcedureButton { - font-size: 11px; - padding: 6px 12px; - background-color: #3B82F6; - color: white; - border: none; - border-radius: 4px; - font-weight: 600; -} - -QPushButton#saveProcedureButton:hover { - background-color: #2563EB; -} - -QPushButton#saveProcedureButton:pressed { - background-color: #1D4ED8; -} - -/* 取消编辑按钮 */ -QPushButton#cancelEditButton { - font-size: 11px; - padding: 6px 12px; - background-color: #6B7280; - color: white; - border: none; - border-radius: 4px; - font-weight: 600; -} - -QPushButton#cancelEditButton:hover { - background-color: #4B5563; -} - -QPushButton#cancelEditButton:pressed { - background-color: #374151; -} - -/* 规程编辑器步骤表格 */ -QTableWidget#stepsTable { - gridline-color: #EBEEF5; - font-size: 11px; - border: 1px solid #DCDFE6; - border-radius: 4px; - background-color: #FFFFFF; - alternate-background-color: #F9FAFC; -} - -QTableWidget#stepsTable::item { - padding: 4px; - border-bottom: 1px solid #EBEEF5; -} - -QTableWidget#stepsTable::item:selected { - background-color: #ECF5FF; - color: #409EFF; -} - -QTableWidget#stepsTable QHeaderView::section { - background-color: #F5F7FA; - color: #606266; - padding: 6px; - border: none; - border-right: 1px solid #EBEEF5; - border-bottom: 1px solid #DCDFE6; - font-weight: bold; - font-size: 11px; -} - -/* ==================== 步骤执行器样式 ==================== */ -/* 超紧凑信息标签 */ -QLabel#ultraCompactInfoLabel { - font-size: 11px; - font-weight: bold; - color: #606266; -} - -/* 超紧凑信息值 */ -QLabel#ultraCompactInfoValue { - font-size: 11px; - color: #374151; -} - -/* 执行状态标签 */ -QLabel#executionStatusLabel { - font-weight: bold; -} - -/* 执行状态 - 成功 */ -QLabel#executionStatusLabel[status="success"] { - color: #059669; -} - -/* 执行状态 - 错误 */ -QLabel#executionStatusLabel[status="error"] { - color: #DC2626; -} - -/* 执行状态 - 警告 */ -QLabel#executionStatusLabel[status="warning"] { - color: #D97706; -} - -/* 执行状态 - 信息 */ -QLabel#executionStatusLabel[status="info"] { - color: #2563EB; -} - -/* ==================== 规程管理界面按钮样式 ==================== */ -/* 卡片标题 */ -QLabel#cardTitle { - font-size: 16px; - font-weight: 600; - color: #1F2937; - padding: 0 0 12px 0; - border-bottom: 2px solid #E5E7EB; - margin-bottom: 16px; -} - -/* 规程统计标签 */ -QLabel#procedureCountLabel { - color: #6B7280; - font-size: 13px; - font-weight: 500; - padding: 6px 12px; - background-color: #F3F4F6; - border-radius: 16px; -} - -/* 搜索框 */ -QLineEdit#searchEdit { - padding: 8px 12px; - font-size: 14px; - border-radius: 6px; - border: 2px solid #E5E7EB; - background-color: #FFFFFF; -} - -QLineEdit#searchEdit:focus { - border-color: #3B82F6; - background-color: #FEFEFF; -} - -/* 类型过滤器 */ -QComboBox#typeFilter { - padding: 8px 12px; - font-size: 14px; - border-radius: 6px; - border: 2px solid #E5E7EB; - background-color: #FFFFFF; - min-width: 120px; -} - -QComboBox#typeFilter:focus { - border-color: #3B82F6; -} - -/* 添加分类按钮 */ -QPushButton#addCategoryBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border: 1px solid #2563EB; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#addCategoryBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); - border-color: #1D4ED8; -} - -QPushButton#addCategoryBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); - border-color: #1E40AF; -} - -/* 删除分类按钮 */ -QPushButton#deleteCategoryBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #EF4444, stop:1 #DC2626); - border: 1px solid #DC2626; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#deleteCategoryBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #DC2626, stop:1 #B91C1C); - border-color: #B91C1C; -} - -QPushButton#deleteCategoryBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B91C1C, stop:1 #991B1B); - border-color: #991B1B; -} - -/* 导入规程按钮 */ -QPushButton#importBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #10B981, stop:1 #059669); - border: 1px solid #059669; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#importBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #059669, stop:1 #047857); - border-color: #047857; -} - -QPushButton#importBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #047857, stop:1 #065F46); - border-color: #065F46; -} - -/* 打开规程按钮 */ -QPushButton#openBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border: 1px solid #2563EB; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#openBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); - border-color: #1D4ED8; -} - -QPushButton#openBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); - border-color: #1E40AF; -} - -/* 导出规程按钮 */ -QPushButton#exportBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F59E0B, stop:1 #D97706); - border: 1px solid #D97706; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#exportBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #D97706, stop:1 #B45309); - border-color: #B45309; -} - -QPushButton#exportBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B45309, stop:1 #92400E); - border-color: #92400E; -} - -/* 删除规程按钮 */ -QPushButton#deleteBtn { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #EF4444, stop:1 #DC2626); - border: 1px solid #DC2626; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border-radius: 6px; - min-height: 32px; -} - -QPushButton#deleteBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #DC2626, stop:1 #B91C1C); - border-color: #B91C1C; -} - -QPushButton#deleteBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B91C1C, stop:1 #991B1B); - border-color: #991B1B; -} - -/* ==================== 历史查看器样式 ==================== */ -/* 历史记录表格 */ -QTableView#historyTable { - gridline-color: #d0d0d0; - background-color: #FFFFFF; - alternate-background-color: #F8FAFC; - selection-background-color: #EBF8FF; - selection-color: #1E40AF; - border: 1px solid #E5E7EB; - border-radius: 6px; - font-size: 13px; -} - -QTableView#historyTable::item { - padding: 8px 12px; - border: none; -} - -QTableView#historyTable::item:hover { - background-color: #F3F4F6; -} - -QTableView#historyTable::item:selected { - background-color: #EBF8FF; - color: #1E40AF; -} - -/* 步骤详情信息组 */ -QWidget#stepDetailInfoGroup { - background-color: #f8f9fa; - border: 1px solid #E5E7EB; - border-radius: 8px; - padding: 16px; -} - -/* 步骤描述文本 */ -QLineEdit#stepDescriptionText { - background-color: #f8f9fa; - border: 1px solid #E5E7EB; - border-radius: 4px; - padding: 8px; - font-size: 13px; - color: #374151; -} - -/* 执行结果文本 - 成功 */ -QLineEdit#stepResultText[status="success"] { - background-color: #d4edda; - border: 1px solid #c3e6cb; - border-radius: 4px; - padding: 8px; - font-size: 13px; - color: #155724; -} - -/* 执行结果文本 - 失败 */ -QLineEdit#stepResultText[status="error"] { - background-color: #f8d7da; - border: 1px solid #f5c6cb; - border-radius: 4px; - padding: 8px; - font-size: 13px; - color: #721c24; -} - -/* 执行结果文本 - 默认 */ -QLineEdit#stepResultText[status="default"] { - background-color: #fff3cd; - border: 1px solid #ffeaa7; - border-radius: 4px; - padding: 8px; - font-size: 13px; - color: #856404; -} - -/* ==================== 规程管理工具栏按钮样式 - 与变量表按钮一致 ==================== */ -/* 工具栏按钮基础样式 - 与变量表保持一致 */ -QToolBar QToolButton { - font-size: 14px; - font-weight: 600; - padding: 10px 16px; - border-radius: 8px; - border: 1px solid; - margin: 3px; - min-width: 90px; - min-height: 36px; - font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; -} - -/* 导入规程按钮 - 绿色主题 (与变量表"开始通讯"一致) */ -#importToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #10B981, stop:1 #059669); - border-color: #059669; -} - -#importToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #059669, stop:1 #047857); - border-color: #047857; -} - -#importToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #047857, stop:1 #065F46); - border-color: #065F46; -} - -/* 添加分类按钮 - 蓝色主题 */ -#addCategoryToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border-color: #2563EB; -} - -#addCategoryToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); - border-color: #1D4ED8; -} - -#addCategoryToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); - border-color: #1E40AF; -} - -/* 删除分类按钮 - 红色主题 */ -#deleteCategoryToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #EF4444, stop:1 #DC2626); - border-color: #DC2626; -} - -#deleteCategoryToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #DC2626, stop:1 #B91C1C); - border-color: #B91C1C; -} - -#deleteCategoryToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B91C1C, stop:1 #991B1B); - border-color: #991B1B; -} - -/* 打开规程按钮 - 蓝色主题 */ -#openProcedureToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #3B82F6, stop:1 #2563EB); - border-color: #2563EB; -} - -#openProcedureToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #2563EB, stop:1 #1D4ED8); - border-color: #1D4ED8; -} - -#openProcedureToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #1D4ED8, stop:1 #1E40AF); - border-color: #1E40AF; -} - -/* 删除规程按钮 - 红色主题 */ -#deleteProcedureToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #EF4444, stop:1 #DC2626); - border-color: #DC2626; -} - -#deleteProcedureToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #DC2626, stop:1 #B91C1C); - border-color: #B91C1C; -} - -#deleteProcedureToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B91C1C, stop:1 #991B1B); - border-color: #991B1B; -} - -/* 历史记录按钮 - 紫色主题 */ -#historyToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #8B5CF6, stop:1 #7C3AED); - border-color: #7C3AED; -} - -#historyToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #7C3AED, stop:1 #6D28D9); - border-color: #6D28D9; -} - -#historyToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6D28D9, stop:1 #5B21B6); - border-color: #5B21B6; -} - -/* 批量执行按钮 - 绿色主题 */ -#batchExecuteToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #10B981, stop:1 #059669); - border-color: #059669; -} - -#batchExecuteToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #059669, stop:1 #047857); - border-color: #047857; -} - -#batchExecuteToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #047857, stop:1 #065F46); - border-color: #065F46; -} - -/* 关键词管理按钮 - 紫色主题 */ -#keywordManageToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #8B5CF6, stop:1 #7C3AED); - border-color: #7C3AED; -} - -#keywordManageToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #7C3AED, stop:1 #6D28D9); - border-color: #6D28D9; -} - -#keywordManageToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6D28D9, stop:1 #5B21B6); - border-color: #5B21B6; -} - -/* 导出规程按钮 - 橙色主题 */ -#exportProcedureToolBtn { - color: #FFFFFF; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #F59E0B, stop:1 #D97706); - border-color: #D97706; -} - -#exportProcedureToolBtn:hover { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #D97706, stop:1 #B45309); - border-color: #B45309; -} - -#exportProcedureToolBtn:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #B45309, stop:1 #92400E); - border-color: #92400E; -}/ -* ==================== 规程管理工具栏按钮样式 - 遵循PyQt5规范 ==================== */ -/* 工具栏按钮基础样式 */ -QToolBar QToolButton { - font-size: 14px; - font-weight: 600; - padding: 10px 16px; - border-radius: 8px; - border: 1px solid #E5E7EB; - margin: 3px; - min-width: 90px; - min-height: 36px; - font-family: "Microsoft YaHei", sans-serif; - color: #FFFFFF; -} - -/* 导入规程按钮 - 绿色主题 */ -#importToolBtn { - background-color: #10B981; - border-color: #059669; -} - -#importToolBtn:hover { - background-color: #059669; - border-color: #047857; -} - -#importToolBtn:pressed { - background-color: #047857; - border-color: #065F46; -} - -/* 添加分类按钮 - 蓝色主题 */ -#addCategoryToolBtn { - background-color: #3B82F6; - border-color: #2563EB; -} - -#addCategoryToolBtn:hover { - background-color: #2563EB; - border-color: #1D4ED8; -} - -#addCategoryToolBtn:pressed { - background-color: #1D4ED8; - border-color: #1E40AF; -} - -/* 删除分类按钮 - 红色主题 */ -#deleteCategoryToolBtn { - background-color: #EF4444; - border-color: #DC2626; -} - -#deleteCategoryToolBtn:hover { - background-color: #DC2626; - border-color: #B91C1C; -} - -#deleteCategoryToolBtn:pressed { - background-color: #B91C1C; - border-color: #991B1B; -} - -/* 打开规程按钮 - 蓝色主题 */ -#openProcedureToolBtn { - background-color: #3B82F6; - border-color: #2563EB; -} - -#openProcedureToolBtn:hover { - background-color: #2563EB; - border-color: #1D4ED8; -} - -#openProcedureToolBtn:pressed { - background-color: #1D4ED8; - border-color: #1E40AF; -} - -/* 删除规程按钮 - 红色主题 */ -#deleteProcedureToolBtn { - background-color: #EF4444; - border-color: #DC2626; -} - -#deleteProcedureToolBtn:hover { - background-color: #DC2626; - border-color: #B91C1C; -} - -#deleteProcedureToolBtn:pressed { - background-color: #B91C1C; - border-color: #991B1B; -} - -/* 历史记录按钮 - 紫色主题 */ -#historyToolBtn { - background-color: #8B5CF6; - border-color: #7C3AED; -} - -#historyToolBtn:hover { - background-color: #7C3AED; - border-color: #6D28D9; -} - -#historyToolBtn:pressed { - background-color: #6D28D9; - border-color: #5B21B6; -} - -/* 批量执行按钮 - 绿色主题 */ -#batchExecuteToolBtn { - background-color: #10B981; - border-color: #059669; -} - -#batchExecuteToolBtn:hover { - background-color: #059669; - border-color: #047857; -} - -#batchExecuteToolBtn:pressed { - background-color: #047857; - border-color: #065F46; -} - -/* 关键词管理按钮 - 紫色主题 */ -#keywordManageToolBtn { - background-color: #8B5CF6; - border-color: #7C3AED; -} - -#keywordManageToolBtn:hover { - background-color: #7C3AED; - border-color: #6D28D9; -} - -#keywordManageToolBtn:pressed { - background-color: #6D28D9; - border-color: #5B21B6; -} - -/* 导出规程按钮 - 橙色主题 */ -#exportProcedureToolBtn { - background-color: #F59E0B; - border-color: #D97706; -} - -#exportProcedureToolBtn:hover { - background-color: #D97706; - border-color: #B45309; -} - -#exportProcedureToolBtn:pressed { - background-color: #B45309; - border-color: #92400E; } \ No newline at end of file diff --git a/Static/ProcedureTable.qss b/Static/ProcedureTable.qss new file mode 100644 index 0000000..5b07e4c --- /dev/null +++ b/Static/ProcedureTable.qss @@ -0,0 +1,249 @@ +/* ==================== DCS2025 规程表格样式 ==================== */ + +/* ==================== 表格基础样式 ==================== */ +QTableView { + background-color: #FFFFFF; + border: 1px solid #E5E7EB; + border-radius: 6px; + gridline-color: #F3F4F6; + font-size: 13px; + color: #374151; + selection-background-color: #EBF8FF; + selection-color: #1E40AF; + outline: none; +} + +/* 表格项基础样式 */ +QTableView::item { + padding: 8px; + border: none; + min-height: 40px; +} + +/* 表格项选中状态 - 整行选中效果 */ +QTableView::item:selected { + background-color: #EBF8FF; + color: #1E40AF; + border: none; +} + +/* 表格项hover状态 - 整行hover效果 */ +QTableView::item:hover { + background-color: #F0F9FF; + color: #1F2937; +} + +/* 表格项选中且hover状态 */ +QTableView::item:selected:hover { + background-color: #DBEAFE; + color: #1565C0; +} + +/* 表格项焦点状态 */ +QTableView::item:focus { + background-color: #EBF8FF; + color: #1E40AF; + outline: none; + border: none; +} + +/* ==================== 表格头部样式 ==================== */ +QHeaderView { + background-color: transparent; + border: none; + outline: none; +} + +QHeaderView::section { + background-color: #F8F9FA; + color: #374151; + font-weight: 600; + font-size: 13px; + padding: 12px 8px; + border: 1px solid #E5E7EB; + border-left: none; + text-align: center; +} + +QHeaderView::section:first { + border-left: 1px solid #E5E7EB; + border-top-left-radius: 6px; +} + +QHeaderView::section:last { + border-top-right-radius: 6px; +} + +QHeaderView::section:hover { + background-color: #F3F4F6; + color: #1F2937; +} + +QHeaderView::section:pressed { + background-color: #E5E7EB; + color: #111827; +} + +/* ==================== 垂直表头隐藏 ==================== */ +QHeaderView::section:vertical { + border: none; + background-color: transparent; +} + +/* ==================== 滚动条样式 ==================== */ +QScrollBar:vertical { + background-color: #F9FAFB; + width: 12px; + border-radius: 6px; + border: none; +} + +QScrollBar::handle:vertical { + background-color: #D1D5DB; + border-radius: 6px; + min-height: 20px; + margin: 2px; +} + +QScrollBar::handle:vertical:hover { + background-color: #9CA3AF; +} + +QScrollBar::handle:vertical:pressed { + background-color: #6B7280; +} + +QScrollBar::add-line:vertical, +QScrollBar::sub-line:vertical { + border: none; + background: none; + height: 0px; +} + +QScrollBar::add-page:vertical, +QScrollBar::sub-page:vertical { + background: none; +} + +QScrollBar:horizontal { + background-color: #F9FAFB; + height: 12px; + border-radius: 6px; + border: none; +} + +QScrollBar::handle:horizontal { + background-color: #D1D5DB; + border-radius: 6px; + min-width: 20px; + margin: 2px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #9CA3AF; +} + +QScrollBar::handle:horizontal:pressed { + background-color: #6B7280; +} + +QScrollBar::add-line:horizontal, +QScrollBar::sub-line:horizontal { + border: none; + background: none; + width: 0px; +} + +QScrollBar::add-page:horizontal, +QScrollBar::sub-page:horizontal { + background: none; +} + +/* ==================== 特殊状态样式 ==================== */ + +/* 执行成功的行 - 绿色主题 */ +QTableView::item[executionStatus="success"] { + background-color: #ECFDF5; + color: #065F46; +} + +QTableView::item[executionStatus="success"]:hover { + background-color: #D1FAE5; + color: #047857; +} + +QTableView::item[executionStatus="success"]:selected { + background-color: #A7F3D0; + color: #064E3B; +} + +/* 执行失败的行 - 红色主题 */ +QTableView::item[executionStatus="failed"] { + background-color: #FEF2F2; + color: #991B1B; +} + +QTableView::item[executionStatus="failed"]:hover { + background-color: #FEE2E2; + color: #7F1D1D; +} + +QTableView::item[executionStatus="failed"]:selected { + background-color: #FECACA; + color: #7F1D1D; +} + +/* 主步骤行 - 灰色主题 */ +QTableView::item[stepType="main"] { + background-color: #F9FAFB; + color: #374151; + font-weight: 600; +} + +QTableView::item[stepType="main"]:hover { + background-color: #F3F4F6; + color: #1F2937; +} + +QTableView::item[stepType="main"]:selected { + background-color: #E5E7EB; + color: #111827; +} + +/* ==================== 网格线样式 ==================== */ +QTableView { + gridline-color: #F3F4F6; + show-decoration-selected: 1; +} + +/* ==================== 文本对齐 ==================== */ +QTableView::item[textAlign="center"] { + text-align: center; +} + +QTableView::item[textAlign="left"] { + text-align: left; +} + +QTableView::item[textAlign="right"] { + text-align: right; +} + +/* ==================== 响应式设计 ==================== */ +QTableView[size="compact"] { + font-size: 12px; +} + +QTableView[size="compact"]::item { + padding: 6px; + min-height: 32px; +} + +QTableView[size="large"] { + font-size: 14px; +} + +QTableView[size="large"]::item { + padding: 10px; + min-height: 48px; +} \ No newline at end of file diff --git a/Static/StepExecutor.qss b/Static/StepExecutor.qss new file mode 100644 index 0000000..3e2598a --- /dev/null +++ b/Static/StepExecutor.qss @@ -0,0 +1,390 @@ +/* ==================== DCS2025 步骤执行器样式 ==================== */ + +/* ==================== 执行按钮样式 ==================== */ + +/* 开始自动执行按钮 - 绿色主题 */ +QPushButton#autoExecuteBtn { + color: #047857; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #ECFDF5; + border-radius: 6px; + border: 1px solid #BBF7D0; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 100px; + min-height: 36px; +} + +QPushButton#autoExecuteBtn:hover { + background-color: #D1FAE5; + border-color: #86EFAC; + color: #065F46; +} + +QPushButton#autoExecuteBtn:pressed { + background-color: #A7F3D0; + border-color: #6EE7B7; + color: #064E3B; +} + +QPushButton#autoExecuteBtn:disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border-color: #E5E7EB; +} + +/* 停止自动执行按钮 - 红色主题 */ +QPushButton#stopExecuteBtn { + color: #B91C1C; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF2F2; + border-radius: 6px; + border: 1px solid #FECACA; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 100px; + min-height: 36px; +} + +QPushButton#stopExecuteBtn:hover { + background-color: #FEE2E2; + border-color: #FCA5A5; + color: #991B1B; +} + +QPushButton#stopExecuteBtn:pressed { + background-color: #FECACA; + border-color: #F87171; + color: #7F1D1D; +} + +QPushButton#stopExecuteBtn:disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border-color: #E5E7EB; +} + +/* 执行下一步按钮 - 蓝色主题 */ +QPushButton#nextStepBtn { + color: #1D4ED8; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #EBF8FF; + border-radius: 6px; + border: 1px solid #BFDBFE; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 100px; + min-height: 36px; +} + +QPushButton#nextStepBtn:hover { + background-color: #DBEAFE; + border-color: #93C5FD; + color: #1E40AF; +} + +QPushButton#nextStepBtn:pressed { + background-color: #BFDBFE; + border-color: #60A5FA; + color: #1E3A8A; +} + +QPushButton#nextStepBtn:disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border-color: #E5E7EB; +} + +/* 完全重置按钮 - 橙色主题 */ +QPushButton#resetExecuteBtn { + color: #D97706; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #FEF3C7; + border-radius: 6px; + border: 1px solid #FCD34D; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 100px; + min-height: 36px; +} + +QPushButton#resetExecuteBtn:hover { + background-color: #FDE68A; + border-color: #FBBF24; + color: #B45309; +} + +QPushButton#resetExecuteBtn:pressed { + background-color: #FCD34D; + border-color: #F59E0B; + color: #92400E; +} + +QPushButton#resetExecuteBtn:disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border-color: #E5E7EB; +} + +/* 生成报告按钮 - 紫色主题 */ +QPushButton#exportReportBtn { + color: #7C3AED; + font-size: 15px; + font-weight: 600; + padding: 8px 16px; + background-color: #F3E8FF; + border-radius: 6px; + border: 1px solid #C4B5FD; + font-family: "PingFangSC-Medium", "Microsoft YaHei", sans-serif; + min-width: 100px; + min-height: 36px; +} + +QPushButton#exportReportBtn:hover { + background-color: #EDE9FE; + border-color: #A78BFA; + color: #6D28D9; +} + +QPushButton#exportReportBtn:pressed { + background-color: #DDD6FE; + border-color: #8B5CF6; + color: #5B21B6; +} + +QPushButton#exportReportBtn:disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border-color: #E5E7EB; +} + +/* ==================== 状态标签样式 ==================== */ + +/* 状态标签基础样式 */ +QLabel#statusLabel { + font-size: 14px; + font-weight: 600; + padding: 6px 12px; + border-radius: 4px; + background-color: #EBF8FF; + color: #1E40AF; + border: 1px solid #BFDBFE; +} + +/* 执行状态标签 */ +QLabel#executionStatusLabel { + font-size: 14px; + font-weight: 600; + padding: 6px 12px; + border-radius: 4px; + border: 1px solid; +} + +/* 成功状态 */ +QLabel#executionStatusLabel[status="success"] { + background-color: #ECFDF5; + color: #065F46; + border-color: #BBF7D0; +} + +/* 错误状态 */ +QLabel#executionStatusLabel[status="error"] { + background-color: #FEF2F2; + color: #991B1B; + border-color: #FECACA; +} + +/* 警告状态 */ +QLabel#executionStatusLabel[status="warning"] { + background-color: #FEF3C7; + color: #92400E; + border-color: #FCD34D; +} + +/* 信息状态 */ +QLabel#executionStatusLabel[status="info"] { + background-color: #EBF8FF; + color: #1E40AF; + border-color: #BFDBFE; +} + +/* ==================== 倒计时标签样式 ==================== */ + +QLabel#countdownLabel { + font-size: 13px; + font-weight: 500; + padding: 4px 8px; + border-radius: 4px; + font-family: "Consolas", "Monaco", monospace; +} + +/* 剩余时间充足 */ +QLabel#countdownLabel[timeRemaining="high"] { + background-color: #ECFDF5; + color: #065F46; + border: 1px solid #BBF7D0; +} + +/* 剩余时间中等 */ +QLabel#countdownLabel[timeRemaining="medium"] { + background-color: #FEF3C7; + color: #92400E; + border: 1px solid #FCD34D; +} + +/* 剩余时间不足 */ +QLabel#countdownLabel[timeRemaining="low"] { + background-color: #FEF2F2; + color: #991B1B; + border: 1px solid #FECACA; +} + +/* 已完成 */ +QLabel#countdownLabel[timeRemaining="completed"] { + background-color: #EBF8FF; + color: #1E40AF; + border: 1px solid #BFDBFE; +} + +/* ==================== 规程信息区域样式 ==================== */ + +/* 规程信息容器 */ +QWidget#procedureInfoContainer { + background-color: #F8F9FA; + border: 1px solid #E5E7EB; + border-radius: 6px; +} + +/* 超紧凑信息组 */ +QWidget#ultraCompactInfoGroup { + background-color: transparent; +} + +/* 超紧凑信息标签 */ +QLabel#ultraCompactInfoLabel { + font-size: 12px; + font-weight: 600; + color: #6B7280; +} + +/* 超紧凑信息值 */ +QLabel#ultraCompactInfoValue { + font-size: 12px; + font-weight: 500; + color: #374151; +} + +/* ==================== 表格样式 ==================== */ + +/* 表格视图基础样式 */ +QTableView { + background-color: #FFFFFF; + border: 1px solid #E5E7EB; + border-radius: 6px; + gridline-color: #F3F4F6; + selection-background-color: #EBF8FF; + selection-color: #1E40AF; + font-size: 13px; + color: #374151; +} + +QTableView::item { + padding: 8px; + border: none; +} + +QTableView::item:hover { + background-color: #F9FAFB; +} + +QTableView::item:selected { + background-color: #EBF8FF; + color: #1E40AF; +} + +/* 表格头部样式 */ +QHeaderView::section { + background-color: #F3F4F6; + color: #374151; + font-weight: 600; + font-size: 13px; + padding: 8px; + border: 1px solid #E5E7EB; + border-left: none; +} + +QHeaderView::section:first { + border-left: 1px solid #E5E7EB; +} + +QHeaderView::section:hover { + background-color: #E5E7EB; +} + +/* ==================== 输入控件样式 ==================== */ + +/* 数值输入框 */ +QSpinBox, QDoubleSpinBox { + background-color: #FFFFFF; + border: 1px solid #E5E7EB; + border-radius: 4px; + padding: 4px 8px; + font-size: 13px; + color: #374151; + min-width: 60px; +} + +QSpinBox:focus, QDoubleSpinBox:focus { + border-color: #3B82F6; + outline: none; +} + +/* 复选框 */ +QCheckBox { + font-size: 13px; + color: #374151; + spacing: 6px; +} + +QCheckBox::indicator { + width: 16px; + height: 16px; + border: 1px solid #D1D5DB; + border-radius: 3px; + background-color: #FFFFFF; +} + +QCheckBox::indicator:checked { + background-color: #3B82F6; + border-color: #3B82F6; + image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjAgMCAxMiAxMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEwIDNMNC41IDguNUwyIDYiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=); +} + +QCheckBox::indicator:hover { + border-color: #9CA3AF; +} + +/* ==================== 标签样式 ==================== */ + +QLabel { + font-size: 13px; + color: #374151; +} + +/* 标题标签 */ +QLabel[class="title"] { + font-size: 16px; + font-weight: 600; + color: #1F2937; +} + +/* 副标题标签 */ +QLabel[class="subtitle"] { + font-size: 14px; + font-weight: 500; + color: #4B5563; +} \ No newline at end of file diff --git a/UI/ProcedureManager/ProcedureManager.py b/UI/ProcedureManager/ProcedureManager.py index aefa2d5..c528e2c 100644 --- a/UI/ProcedureManager/ProcedureManager.py +++ b/UI/ProcedureManager/ProcedureManager.py @@ -7,7 +7,7 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableView, QToolButton, QLabel, QCheckBox, QSpinBox, QMenu, QFileDialog, QTabWidget, QTabBar, QListWidget, QListWidgetItem, QDialog, QLineEdit, QFormLayout, QDialogButtonBox, QMessageBox, - QHeaderView, QToolBar, QAction, QStatusBar, QSplitter, QAbstractItemView) + QHeaderView, QToolBar, QAction, QStatusBar, QSplitter, QAbstractItemView, QFrame) from docx import Document from docx.shared import Pt, RGBColor from docx.enum.text import WD_PARAGRAPH_ALIGNMENT @@ -16,7 +16,7 @@ import qtawesome as qta from datetime import datetime # 导入其他模块 -from model.ProcedureModel.ProcedureProcessor import ExcelParser, StepTableModel +from model.ProcedureModel.ProcedureProcessor import ExcelParser from utils.DBModels.ProcedureModel import DatabaseManager from UI.ProcedureManager.HistoryViewer import HistoryViewerWidget from UI.ProcedureManager.StepExecutor import StepExecutor # 修改导入路径 @@ -80,35 +80,134 @@ class ProcedureManager(QMainWindow): self.setWindowTitle("规程管理系统") self.setGeometry(100, 100, 1200, 800) - # 创建工具栏 - 优化图标大小和布局 - self.toolbar = QToolBar("主工具栏") - self.toolbar.setIconSize(QSize(12, 12)) # 减小图标尺寸避免遮盖 - self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # 文字在图标旁边 - self.toolbar.setMaximumHeight(50) # 适当的工具栏高度 - self.toolbar.setContentsMargins(0, 0, 0, 0) # 移除边距 - self.addToolBar(self.toolbar) - self.createActions() + + # 初始化数据库 + self.initDB() + + # 创建顶部按钮布局 + self.createTopButtonLayout() + + def setupButtonIcon(self, button, icon_name, color): + """设置按钮图标,支持不同状态的颜色变化""" + # 正常状态图标 + normal_icon = qta.icon(icon_name, color=color) + + # 悬停状态图标(稍微亮一些) + hover_color = self.lightenColor(color, 0.2) + hover_icon = qta.icon(icon_name, color=hover_color) + + # 按下状态图标(稍微暗一些) + pressed_color = self.darkenColor(color, 0.2) + pressed_icon = qta.icon(icon_name, color=pressed_color) + + # 设置图标 + button.setIcon(normal_icon) + + # 存储不同状态的图标,用于状态切换 + button._normal_icon = normal_icon + button._hover_icon = hover_icon + button._pressed_icon = pressed_icon + + # 连接事件 + button.enterEvent = lambda event: self.onButtonEnter(button, event) + button.leaveEvent = lambda event: self.onButtonLeave(button, event) + button.mousePressEvent = lambda event: self.onButtonPress(button, event) + button.mouseReleaseEvent = lambda event: self.onButtonRelease(button, event) + + def lightenColor(self, color, factor): + """使颜色变亮""" + if color.startswith('#'): + # 十六进制颜色 + r = int(color[1:3], 16) + g = int(color[3:5], 16) + b = int(color[5:7], 16) + + r = min(255, int(r + (255 - r) * factor)) + g = min(255, int(g + (255 - g) * factor)) + b = min(255, int(b + (255 - b) * factor)) + + return f"#{r:02x}{g:02x}{b:02x}" + return color + + def darkenColor(self, color, factor): + """使颜色变暗""" + if color.startswith('#'): + # 十六进制颜色 + r = int(color[1:3], 16) + g = int(color[3:5], 16) + b = int(color[5:7], 16) + + r = max(0, int(r * (1 - factor))) + g = max(0, int(g * (1 - factor))) + b = max(0, int(b * (1 - factor))) + + return f"#{r:02x}{g:02x}{b:02x}" + return color + + def onButtonEnter(self, button, event): + """按钮鼠标进入事件""" + if hasattr(button, '_hover_icon'): + button.setIcon(button._hover_icon) + # 调用原始的enterEvent + QPushButton.enterEvent(button, event) + + def onButtonLeave(self, button, event): + """按钮鼠标离开事件""" + if hasattr(button, '_normal_icon'): + button.setIcon(button._normal_icon) + # 调用原始的leaveEvent + QPushButton.leaveEvent(button, event) + + def onButtonPress(self, button, event): + """按钮鼠标按下事件""" + if hasattr(button, '_pressed_icon'): + button.setIcon(button._pressed_icon) + # 调用原始的mousePressEvent + QPushButton.mousePressEvent(button, event) + + def onButtonRelease(self, button, event): + """按钮鼠标释放事件""" + # 检查鼠标是否还在按钮上 + if button.rect().contains(event.pos()): + if hasattr(button, '_hover_icon'): + button.setIcon(button._hover_icon) + else: + if hasattr(button, '_normal_icon'): + button.setIcon(button._normal_icon) + # 调用原始的mouseReleaseEvent + QPushButton.mouseReleaseEvent(button, event) # 添加状态栏 - self.statusBar = QStatusBar() - self.setStatusBar(self.statusBar) - # 批量执行相关变量 - self.batchExecutionQueue = [] # 批量执行队列 - self.currentBatchIndex = 0 # 当前执行的规程索引 - self.isBatchExecuting = False # 是否正在批量执行 - self.batchExecutionTimer = QTimer() # 批量执行检查定时器 - self.batchExecutionTimer.timeout.connect(self.checkBatchExecutionStatus) - self.currentBatchTabIndex = -1 # 当前批量执行的标签页索引 def initUI(self): - # 加载样式表 - self.loadStylesheet() + # 创建主容器 + mainContainer = QWidget() + mainLayout = QVBoxLayout() + mainLayout.setSpacing(0) + mainLayout.setContentsMargins(0, 0, 0, 0) + # 添加顶部按钮布局 + mainLayout.addWidget(self.topButtonWidget) # 创建主控件 - 已经是QTabWidget self.tabs = QTabWidget() - self.setCentralWidget(self.tabs) + # 设置标签页样式,消除边距 + self.tabs.setStyleSheet(""" + QTabWidget::pane { + border: none; + margin: 0px; + padding: 0px; + } + QTabWidget::tab-bar { + alignment: left; + } + """) + mainLayout.addWidget(self.tabs) + + # 设置主容器 + mainContainer.setLayout(mainLayout) + self.setCentralWidget(mainContainer) # 启用标签页关闭按钮 self.tabs.setTabsClosable(True) @@ -127,6 +226,18 @@ class ProcedureManager(QMainWindow): # 初始化标签锁定状态 self.activeExecutorIndex = -1 + self.loadStylesheet() + + self.statusBar = QStatusBar() + self.setStatusBar(self.statusBar) + + # 批量执行相关变量 + self.batchExecutionQueue = [] # 批量执行队列 + self.currentBatchIndex = 0 # 当前执行的规程索引 + self.isBatchExecuting = False # 是否正在批量执行 + self.batchExecutionTimer = QTimer() # 批量执行检查定时器 + self.batchExecutionTimer.timeout.connect(self.checkBatchExecutionStatus) + self.currentBatchTabIndex = -1 # 当前批量执行的标签页索引 def initDB(self): # 初始化数据库 @@ -228,20 +339,18 @@ class ProcedureManager(QMainWindow): mainWidget = QWidget() mainWidget.setStyleSheet("background-color: #F5F7FA;") - # 主布局 - 优化边距去除空白 + # 主布局 - 删除边距以消除空白区域 mainLayout = QHBoxLayout() - mainLayout.setSpacing(8) - mainLayout.setContentsMargins(8, 8, 8, 8) + mainLayout.setSpacing(4) + mainLayout.setContentsMargins(0, 0, 0, 0) # 左侧分类卡片 categoryCard = QWidget() categoryCard.setObjectName("categoryCard") - categoryCard.setFixedWidth(280) - categoryCard.setMaximumHeight(600) categoryLayout = QVBoxLayout() - categoryLayout.setSpacing(16) - categoryLayout.setContentsMargins(0, 0, 0, 0) + categoryLayout.setSpacing(8) + categoryLayout.setContentsMargins(8, 8, 8, 8) # 分类标题 categoryTitle = QLabel("规程分类") @@ -262,22 +371,6 @@ class ProcedureManager(QMainWindow): categoryLayout.addWidget(self.categoryList) # 分类操作按钮 - categoryButtonLayout = QHBoxLayout() - categoryButtonLayout.setSpacing(8) - - addCategoryBtn = QPushButton("添加分类") - addCategoryBtn.setObjectName("addCategoryBtn") - addCategoryBtn.clicked.connect(self.addCategory) - addCategoryBtn.setIcon(qta.icon('fa5s.plus', color='white')) - - deleteCategoryBtn = QPushButton("删除分类") - deleteCategoryBtn.setObjectName("deleteCategoryBtn") - deleteCategoryBtn.clicked.connect(self.deleteCurrentCategory) - deleteCategoryBtn.setIcon(qta.icon('fa5s.trash', color='white')) - - categoryButtonLayout.addWidget(addCategoryBtn) - categoryButtonLayout.addWidget(deleteCategoryBtn) - categoryLayout.addLayout(categoryButtonLayout) categoryCard.setLayout(categoryLayout) @@ -286,8 +379,8 @@ class ProcedureManager(QMainWindow): procedureCard.setObjectName("procedureCard") procedureLayout = QVBoxLayout() - procedureLayout.setSpacing(16) - procedureLayout.setContentsMargins(0, 0, 0, 0) + procedureLayout.setSpacing(8) + procedureLayout.setContentsMargins(8, 8, 8, 8) # 规程标题和统计信息 procedureHeaderLayout = QHBoxLayout() @@ -338,37 +431,7 @@ class ProcedureManager(QMainWindow): procedureLayout.addWidget(self.procedureList) - # 规程操作按钮 - procedureButtonLayout = QHBoxLayout() - procedureButtonLayout.setSpacing(8) - - importBtn = QPushButton("导入规程") - importBtn.setObjectName("importBtn") - importBtn.clicked.connect(self.importProcedure) - importBtn.setIcon(qta.icon('fa5s.file-import', color='white')) - - openBtn = QPushButton("打开规程") - openBtn.setObjectName("openBtn") - openBtn.clicked.connect(self.openProcedureInExecutor) - openBtn.setIcon(qta.icon('fa5s.folder-open', color='white')) - - exportBtn = QPushButton("导出规程") - exportBtn.setObjectName("exportBtn") - exportBtn.clicked.connect(self.exportSelectedProcedure) - exportBtn.setIcon(qta.icon('fa5s.file-export', color='white')) - - deleteBtn = QPushButton("删除规程") - deleteBtn.setObjectName("deleteBtn") - deleteBtn.clicked.connect(self.deleteSelectedProcedure) - deleteBtn.setIcon(qta.icon('fa5s.trash', color='white')) - - procedureButtonLayout.addWidget(importBtn) - procedureButtonLayout.addWidget(openBtn) - procedureButtonLayout.addWidget(exportBtn) - procedureButtonLayout.addWidget(deleteBtn) - procedureButtonLayout.addStretch() - - procedureLayout.addLayout(procedureButtonLayout) + procedureCard.setLayout(procedureLayout) @@ -379,152 +442,126 @@ class ProcedureManager(QMainWindow): mainWidget.setLayout(mainLayout) self.tabs.addTab(mainWidget, "规程管理") - def getButtonStyle(self, bg_color, border_color, hover_bg, hover_border, pressed_bg, pressed_border): - """生成统一的按钮样式""" - return f""" - QToolButton {{ - background-color: {bg_color}; - border: 1px solid {border_color}; - border-radius: 6px; - padding: 6px 12px; - color: #FFFFFF; - font-size: 13px; - font-weight: 600; - min-width: 80px; - min-height: 32px; - font-family: "Microsoft YaHei", sans-serif; - }} - QToolButton:hover {{ - background-color: {hover_bg}; - border-color: {hover_border}; - }} - QToolButton:pressed {{ - background-color: {pressed_bg}; - border-color: {pressed_border}; - }} - """ - def createActions(self): + + def createTopButtonLayout(self): + """创建顶部按钮布局""" + # 创建顶部按钮容器 + self.topButtonWidget = QWidget() + self.topButtonWidget.setObjectName("topButtonWidget") + self.topButtonWidget.setFixedHeight(60) + self.topButtonWidget.setStyleSheet(""" + QWidget#topButtonWidget { + background-color: #FFFFFF; + border-bottom: 1px solid #E5E7EB; + } + """) + + # 创建横向布局 + buttonLayout = QHBoxLayout() + buttonLayout.setSpacing(8) + buttonLayout.setContentsMargins(16, 8, 16, 8) + # 导入规程按钮 - 绿色主题 - self.importBtn = QToolButton() + self.importBtn = QPushButton("导入规程") self.importBtn.setObjectName("importToolBtn") - self.importBtn.setIcon(qta.icon('fa5s.file-import', color='#FFFFFF')) - self.importBtn.setText("导入规程") - self.importBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.importBtn.setIconSize(QSize(18, 18)) self.importBtn.setStatusTip("导入Excel规程文件") - self.importBtn.setStyleSheet(self.getButtonStyle( - "#10B981", "#059669", "#059669", "#047857", "#047857", "#065F46" - )) self.importBtn.clicked.connect(self.importProcedure) - self.toolbar.addWidget(self.importBtn) + self.setupButtonIcon(self.importBtn, 'fa5s.file-import', '#047857') + buttonLayout.addWidget(self.importBtn) # 添加分类按钮 - 蓝色主题 - self.addCategoryBtn = QToolButton() + self.addCategoryBtn = QPushButton("添加分类") self.addCategoryBtn.setObjectName("addCategoryToolBtn") - self.addCategoryBtn.setIcon(qta.icon('fa5s.folder-plus', color='#FFFFFF')) - self.addCategoryBtn.setText("添加分类") - self.addCategoryBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.addCategoryBtn.setIconSize(QSize(18, 18)) self.addCategoryBtn.setStatusTip("添加新的分类") - self.addCategoryBtn.setStyleSheet(self.getButtonStyle( - "#3B82F6", "#2563EB", "#2563EB", "#1D4ED8", "#1D4ED8", "#1E40AF" - )) self.addCategoryBtn.clicked.connect(self.addCategory) - self.toolbar.addWidget(self.addCategoryBtn) + self.setupButtonIcon(self.addCategoryBtn, 'fa5s.folder-plus', '#1D4ED8') + buttonLayout.addWidget(self.addCategoryBtn) # 删除分类按钮 - 红色主题 - self.deleteCategoryBtn = QToolButton() + self.deleteCategoryBtn = QPushButton("删除分类") self.deleteCategoryBtn.setObjectName("deleteCategoryToolBtn") - self.deleteCategoryBtn.setIcon(qta.icon('fa5s.folder-minus', color='#FFFFFF')) - self.deleteCategoryBtn.setText("删除分类") - self.deleteCategoryBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.deleteCategoryBtn.setIconSize(QSize(18, 18)) self.deleteCategoryBtn.setStatusTip("删除当前分类") - self.deleteCategoryBtn.setStyleSheet(self.getButtonStyle( - "#EF4444", "#DC2626", "#DC2626", "#B91C1C", "#B91C1C", "#991B1B" - )) self.deleteCategoryBtn.clicked.connect(self.deleteCurrentCategory) - self.toolbar.addWidget(self.deleteCategoryBtn) + self.setupButtonIcon(self.deleteCategoryBtn, 'fa5s.folder-minus', '#B91C1C') + buttonLayout.addWidget(self.deleteCategoryBtn) - self.toolbar.addSeparator() + # 添加分隔符 + separator1 = QFrame() + separator1.setFrameShape(QFrame.VLine) + separator1.setFrameShadow(QFrame.Sunken) + separator1.setStyleSheet("QFrame { color: #E5E7EB; }") + buttonLayout.addWidget(separator1) # 打开规程按钮 - 蓝色主题 - self.openProcedureBtn = QToolButton() + self.openProcedureBtn = QPushButton("打开规程") self.openProcedureBtn.setObjectName("openProcedureToolBtn") - self.openProcedureBtn.setIcon(qta.icon('fa5s.folder-open', color='#FFFFFF')) - self.openProcedureBtn.setText("打开规程") - self.openProcedureBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.openProcedureBtn.setIconSize(QSize(18, 18)) self.openProcedureBtn.setStatusTip("在步骤执行工具中打开选中的规程") - self.openProcedureBtn.setStyleSheet(self.getButtonStyle( - "#3B82F6", "#2563EB", "#2563EB", "#1D4ED8", "#1D4ED8", "#1E40AF" - )) self.openProcedureBtn.clicked.connect(self.openProcedureInExecutor) - self.toolbar.addWidget(self.openProcedureBtn) + self.setupButtonIcon(self.openProcedureBtn, 'fa5s.folder-open', '#1D4ED8') + buttonLayout.addWidget(self.openProcedureBtn) # 删除规程按钮 - 红色主题 - self.deleteProcedureBtn = QToolButton() + self.deleteProcedureBtn = QPushButton("删除规程") self.deleteProcedureBtn.setObjectName("deleteProcedureToolBtn") - self.deleteProcedureBtn.setIcon(qta.icon('fa5s.trash', color='#FFFFFF')) - self.deleteProcedureBtn.setText("删除规程") - self.deleteProcedureBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.deleteProcedureBtn.setIconSize(QSize(18, 18)) self.deleteProcedureBtn.setStatusTip("删除选中的规程") - self.deleteProcedureBtn.setStyleSheet(self.getButtonStyle( - "#EF4444", "#DC2626", "#DC2626", "#B91C1C", "#B91C1C", "#991B1B" - )) self.deleteProcedureBtn.clicked.connect(self.deleteSelectedProcedure) - self.toolbar.addWidget(self.deleteProcedureBtn) + self.setupButtonIcon(self.deleteProcedureBtn, 'fa5s.trash', '#B91C1C') + buttonLayout.addWidget(self.deleteProcedureBtn) - self.toolbar.addSeparator() + # 添加分隔符 + separator2 = QFrame() + separator2.setFrameShape(QFrame.VLine) + separator2.setFrameShadow(QFrame.Sunken) + separator2.setStyleSheet("QFrame { color: #E5E7EB; }") + buttonLayout.addWidget(separator2) # 历史记录按钮 - 紫色主题 - self.historyBtn = QToolButton() + self.historyBtn = QPushButton("历史记录") self.historyBtn.setObjectName("historyToolBtn") - self.historyBtn.setIcon(qta.icon('fa5s.history', color='#FFFFFF')) - self.historyBtn.setText("历史记录") - self.historyBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.historyBtn.setIconSize(QSize(18, 18)) self.historyBtn.setStatusTip("查看历史执行记录") - self.historyBtn.setStyleSheet(self.getButtonStyle( - "#8B5CF6", "#7C3AED", "#7C3AED", "#6D28D9", "#6D28D9", "#5B21B6" - )) self.historyBtn.clicked.connect(self.openHistoryViewer) - self.toolbar.addWidget(self.historyBtn) + self.setupButtonIcon(self.historyBtn, 'fa5s.history', '#7C3AED') + buttonLayout.addWidget(self.historyBtn) # 批量执行按钮 - 绿色主题 - self.batchExecuteBtn = QToolButton() + self.batchExecuteBtn = QPushButton("批量执行") self.batchExecuteBtn.setObjectName("batchExecuteToolBtn") - self.batchExecuteBtn.setIcon(qta.icon('fa5s.play-circle', color='#FFFFFF')) - self.batchExecuteBtn.setText("批量执行") - self.batchExecuteBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.batchExecuteBtn.setIconSize(QSize(18, 18)) self.batchExecuteBtn.setStatusTip("按顺序批量执行当前分类中的所有规程") - self.batchExecuteBtn.setStyleSheet(self.getButtonStyle( - "#10B981", "#059669", "#059669", "#047857", "#047857", "#065F46" - )) self.batchExecuteBtn.clicked.connect(self.batchExecuteProcedures) - self.toolbar.addWidget(self.batchExecuteBtn) + self.setupButtonIcon(self.batchExecuteBtn, 'fa5s.play-circle', '#047857') + buttonLayout.addWidget(self.batchExecuteBtn) # 关键词管理按钮 - 紫色主题 - self.keywordManageBtn = QToolButton() + self.keywordManageBtn = QPushButton("关键词管理") self.keywordManageBtn.setObjectName("keywordManageToolBtn") - self.keywordManageBtn.setIcon(qta.icon('fa5s.key', color='#FFFFFF')) - self.keywordManageBtn.setText("关键词管理") - self.keywordManageBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.keywordManageBtn.setIconSize(QSize(18, 18)) self.keywordManageBtn.setStatusTip("管理执行步骤关键词字段库") - self.keywordManageBtn.setStyleSheet(self.getButtonStyle( - "#8B5CF6", "#7C3AED", "#7C3AED", "#6D28D9", "#6D28D9", "#5B21B6" - )) self.keywordManageBtn.clicked.connect(self.openKeywordManager) - self.toolbar.addWidget(self.keywordManageBtn) + self.setupButtonIcon(self.keywordManageBtn, 'fa5s.key', '#7C3AED') + buttonLayout.addWidget(self.keywordManageBtn) # 导出规程按钮 - 橙色主题 - self.exportProcedureBtn = QToolButton() + self.exportProcedureBtn = QPushButton("导出规程") self.exportProcedureBtn.setObjectName("exportProcedureToolBtn") - self.exportProcedureBtn.setIcon(qta.icon('fa5s.file-export', color='#FFFFFF')) - self.exportProcedureBtn.setText("导出规程") - self.exportProcedureBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.exportProcedureBtn.setIconSize(QSize(18, 18)) self.exportProcedureBtn.setStatusTip("导出规程为Excel文件") - self.exportProcedureBtn.setStyleSheet(self.getButtonStyle( - "#F59E0B", "#D97706", "#D97706", "#B45309", "#B45309", "#92400E" - )) self.exportProcedureBtn.clicked.connect(self.exportSelectedProcedure) - self.toolbar.addWidget(self.exportProcedureBtn) + self.setupButtonIcon(self.exportProcedureBtn, 'fa5s.file-export', '#D97706') + buttonLayout.addWidget(self.exportProcedureBtn) + + # 添加弹性空间,将按钮推到左侧 + buttonLayout.addStretch() + + # 设置布局 + self.topButtonWidget.setLayout(buttonLayout) def loadCategories(self): self.categoryList.clear() @@ -758,31 +795,18 @@ class ProcedureManager(QMainWindow): def loadStylesheet(self): qssPath = "Static/Procedure.qss" - try: - # 尝试加载优化版QSS,如果不存在则使用原版QSS - optimizedQssPath = "Static/Procedure_optimized.qss" - qssFile = QFile(optimizedQssPath) - if qssFile.exists(): - qssFile.open(QFile.ReadOnly | QFile.Text) - stream = QTextStream(qssFile) - stream.setCodec("UTF-8") - self.setStyleSheet(stream.readAll()) - qssFile.close() - print("已加载优化版样式表") - else: # 回退到原始QSS - qssFile = QFile(qssPath) - if qssFile.exists(): - qssFile.open(QFile.ReadOnly | QFile.Text) - stream = QTextStream(qssFile) - stream.setCodec("UTF-8") - self.setStyleSheet(stream.readAll()) - qssFile.close() - print(f"成功加载样式表: {qssPath}") + qssFile = QFile(qssPath) + if qssFile.exists(): + qssFile.open(QFile.ReadOnly | QFile.Text) + stream = QTextStream(qssFile) + stream.setCodec("UTF-8") + self.setStyleSheet(stream.readAll()) + qssFile.close() + # print(f"成功加载样式表: {qssPath}") # else: # print(f"警告:样式表文件不存在: {qssPath}") - except Exception as e: - print(f"加载样式表失败: {str(e)}") + def closeEvent(self, event): self.db.close() diff --git a/UI/ProcedureManager/StepExecutor.py b/UI/ProcedureManager/StepExecutor.py index 796d25c..e25237a 100644 --- a/UI/ProcedureManager/StepExecutor.py +++ b/UI/ProcedureManager/StepExecutor.py @@ -21,7 +21,8 @@ from openpyxl import Workbook from openpyxl.styles import Font, Alignment, PatternFill from openpyxl.utils import get_column_letter -from model.ProcedureModel.ProcedureProcessor import StepTableModel +from UI.ProcedureManager.ProcedureTable import * +# from model.ProcedureModel.ProcedureProcessor import StepTableModel from utils.DBModels.ProcedureModel import DatabaseManager from utils import Globals @@ -48,6 +49,114 @@ class StepExecutor(QWidget): self.initUi(testSteps) self.initExecutionState() self.initTimers() + self.loadStylesheet() + + def setupButtonIcon(self, button, icon_name, color): + """设置按钮图标,支持不同状态的颜色变化""" + # 正常状态图标 + normal_icon = qta.icon(icon_name, color=color) + + # 悬停状态图标(稍微亮一些) + hover_color = self.lightenColor(color, 0.2) + hover_icon = qta.icon(icon_name, color=hover_color) + + # 按下状态图标(稍微暗一些) + pressed_color = self.darkenColor(color, 0.2) + pressed_icon = qta.icon(icon_name, color=pressed_color) + + # 设置图标 + button.setIcon(normal_icon) + + # 存储不同状态的图标,用于状态切换 + button._normal_icon = normal_icon + button._hover_icon = hover_icon + button._pressed_icon = pressed_icon + + # 连接事件 + button.enterEvent = lambda event: self.onButtonEnter(button, event) + button.leaveEvent = lambda event: self.onButtonLeave(button, event) + button.mousePressEvent = lambda event: self.onButtonPress(button, event) + button.mouseReleaseEvent = lambda event: self.onButtonRelease(button, event) + + def lightenColor(self, color, factor): + """使颜色变亮""" + if color.startswith('#'): + # 十六进制颜色 + r = int(color[1:3], 16) + g = int(color[3:5], 16) + b = int(color[5:7], 16) + + r = min(255, int(r + (255 - r) * factor)) + g = min(255, int(g + (255 - g) * factor)) + b = min(255, int(b + (255 - b) * factor)) + + return f"#{r:02x}{g:02x}{b:02x}" + return color + + def darkenColor(self, color, factor): + """使颜色变暗""" + if color.startswith('#'): + # 十六进制颜色 + r = int(color[1:3], 16) + g = int(color[3:5], 16) + b = int(color[5:7], 16) + + r = max(0, int(r * (1 - factor))) + g = max(0, int(g * (1 - factor))) + b = max(0, int(b * (1 - factor))) + + return f"#{r:02x}{g:02x}{b:02x}" + return color + + def onButtonEnter(self, button, event): + """按钮鼠标进入事件""" + if hasattr(button, '_hover_icon'): + button.setIcon(button._hover_icon) + # 调用原始的enterEvent + QPushButton.enterEvent(button, event) + + def onButtonLeave(self, button, event): + """按钮鼠标离开事件""" + if hasattr(button, '_normal_icon'): + button.setIcon(button._normal_icon) + # 调用原始的leaveEvent + QPushButton.leaveEvent(button, event) + + def onButtonPress(self, button, event): + """按钮鼠标按下事件""" + if hasattr(button, '_pressed_icon'): + button.setIcon(button._pressed_icon) + # 调用原始的mousePressEvent + QPushButton.mousePressEvent(button, event) + + def onButtonRelease(self, button, event): + """按钮鼠标释放事件""" + # 检查鼠标是否还在按钮上 + if button.rect().contains(event.pos()): + if hasattr(button, '_hover_icon'): + button.setIcon(button._hover_icon) + else: + if hasattr(button, '_normal_icon'): + button.setIcon(button._normal_icon) + # 调用原始的mouseReleaseEvent + QPushButton.mouseReleaseEvent(button, event) + + def loadStylesheet(self): + """加载样式表""" + try: + qssPath = "Static/StepExecutor.qss" + qssFile = QFile(qssPath) + if qssFile.exists(): + qssFile.open(QFile.ReadOnly | QFile.Text) + stream = QTextStream(qssFile) + stream.setCodec("UTF-8") + self.setStyleSheet(stream.readAll()) + qssFile.close() + print(f"✅ StepExecutor成功加载样式表: {qssPath}") + else: + print(f"⚠️ StepExecutor样式表文件不存在: {qssPath}") + except Exception as e: + print(f"❌ StepExecutor加载样式表失败: {str(e)}") def initExecutionState(self): """初始化执行状态""" @@ -78,7 +187,10 @@ class StepExecutor(QWidget): layout = QVBoxLayout() self.createInfoSection(layout) - self.createTableSection(layout, testSteps) + # self.createTableSection(layout, testSteps) + self.tableView = ProcedureTabel(testSteps, self) + layout.addWidget(self.tableView) + self.tableModel = self.tableView.tableModel self.createControlSection(layout) self.createSettingsSection(layout) layout.setSpacing(0) @@ -255,134 +367,62 @@ class StepExecutor(QWidget): return groupWidget - def createTableSection(self, layout, testSteps): - """创建表格区域""" - try: - self.tableModel = StepTableModel(testSteps) - self.tableView = QTableView() - self.tableView.setModel(self.tableModel) - self.tableView.setContextMenuPolicy(Qt.CustomContextMenu) - self.tableView.customContextMenuRequested.connect(self.showContextMenu) - - # 设置表格编辑行为 - self.tableView.setEditTriggers(QTableView.DoubleClicked) - self.tableView.setSelectionBehavior(QTableView.SelectRows) - - # 设置表格显示优化 - self.tableView.setAlternatingRowColors(False) # 交替行颜色 - self.tableView.setShowGrid(True) # 显示网格线 - self.tableView.setGridStyle(Qt.SolidLine) # 实线网格 - self.tableView.setSortingEnabled(False) # 禁用排序避免干扰执行顺序 - - # 设置最小行高 - self.tableView.verticalHeader().setMinimumSectionSize(30) - - self.setupTableHeaders() - - # 初始调整所有行高 - self.adjustAllRowHeights() - - layout.addWidget(QLabel("测试步骤:")) - layout.addWidget(self.tableView) - - except Exception as e: - print(f"创建表格区域时出错: {e}") - import traceback - traceback.print_exc() - # 如果出错,至少创建一个空的表格 - self.tableView = QTableView() - layout.addWidget(QLabel("测试步骤:")) - layout.addWidget(self.tableView) - - def setupTableHeaders(self): - """设置表格头部""" - try: - header = self.tableView.horizontalHeader() - if header: - # 设置表格自动调整行高 - self.tableView.verticalHeader().setDefaultSectionSize(35) - self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) - - # 设置列宽模式 - 让表格填充满整个宽度 - header.setStretchLastSection(True) # 让最后一列自动拉伸填充剩余空间 - - # 设置各列的调整模式 - header.setSectionResizeMode(0, QHeaderView.Fixed) # 步骤ID - 固定宽度 - header.setSectionResizeMode(1, QHeaderView.Stretch) # 步骤描述 - 拉伸 - header.setSectionResizeMode(2, QHeaderView.Fixed) # 操作类型 - 固定宽度 - header.setSectionResizeMode(3, QHeaderView.Fixed) # 执行时间 - 固定宽度 - header.setSectionResizeMode(4, QHeaderView.Fixed) # 执行结果 - 固定宽度 - header.setSectionResizeMode(5, QHeaderView.Stretch) # 详细结果 - 拉伸 - header.setSectionResizeMode(6, QHeaderView.Stretch) # 备注 - 拉伸 - - # 设置固定列的宽度 - self.tableView.setColumnWidth(0, 80) # 步骤ID - self.tableView.setColumnWidth(2, 120) # 操作类型 - self.tableView.setColumnWidth(3, 160) # 执行时间 - self.tableView.setColumnWidth(4, 80) # 执行结果 - - # 设置拉伸列的最小宽度 - header.setMinimumSectionSize(100) # 设置所有列的最小宽度 - - # 启用文本换行 - self.tableView.setWordWrap(True) - - except Exception as e: - print(f"设置表格头部时出错: {e}") + def createControlSection(self, layout): """创建控制按钮区域""" controlLayout = QHBoxLayout() + controlLayout.setSpacing(12) + controlLayout.setContentsMargins(8, 8, 8, 8) # 开始自动执行按钮 - 绿色主题 self.autoButton = QPushButton("开始自动执行") + self.autoButton.setObjectName("autoExecuteBtn") + self.autoButton.setIconSize(QSize(18, 18)) self.autoButton.clicked.connect(self.startAutoExecute) - self.autoButton.setIcon(qta.icon('fa5s.play', color='white')) self.autoButton.setToolTip("开始自动执行整个规程流程\n将按照设定的轮次和间隔时间自动执行所有步骤") + self.setupButtonIcon(self.autoButton, 'fa5s.play', '#047857') # 停止自动执行按钮 - 红色主题 self.stopButton = QPushButton("停止自动执行") + self.stopButton.setObjectName("stopExecuteBtn") + self.stopButton.setIconSize(QSize(18, 18)) self.stopButton.clicked.connect(self.stopAutoExecute) self.stopButton.setEnabled(False) - self.stopButton.setIcon(qta.icon('fa5s.stop', color='white')) self.stopButton.setToolTip("停止当前正在执行的自动流程\n可以随时中断执行过程") + self.setupButtonIcon(self.stopButton, 'fa5s.stop', '#B91C1C') # 执行下一步按钮 - 蓝色主题 self.nextButton = QPushButton("执行下一步") + self.nextButton.setObjectName("nextStepBtn") + self.nextButton.setIconSize(QSize(18, 18)) self.nextButton.clicked.connect(self.executeNextStep) - self.nextButton.setIcon(qta.icon('fa5s.step-forward', color='white')) self.nextButton.setToolTip("手动执行下一个步骤\n用于单步调试和手动控制执行过程") + self.setupButtonIcon(self.nextButton, 'fa5s.step-forward', '#1D4ED8') # 完全重置按钮 - 橙色主题 self.resetButton = QPushButton("完全重置") + self.resetButton.setObjectName("resetExecuteBtn") + self.resetButton.setIconSize(QSize(18, 18)) self.resetButton.clicked.connect(self.resetExecution) - self.resetButton.setIcon(qta.icon('fa5s.redo', color='white')) self.resetButton.setToolTip("重置所有执行状态\n清除所有步骤的执行结果和进度") + self.setupButtonIcon(self.resetButton, 'fa5s.redo', '#D97706') # 生成报告按钮 - 紫色主题 self.exportButton = QPushButton("生成报告") + self.exportButton.setObjectName("exportReportBtn") + self.exportButton.setIconSize(QSize(18, 18)) self.exportButton.clicked.connect(self.onExportReportClicked) - self.exportButton.setIcon(qta.icon('fa5s.file-alt', color='white')) self.exportButton.setToolTip("生成执行报告\n导出详细的执行结果和统计数据") + self.setupButtonIcon(self.exportButton, 'fa5s.file-alt', '#7C3AED') - # 创建按钮分组布局 - # 第一组:执行控制按钮 - executionGroup = QHBoxLayout() - executionGroup.addWidget(self.autoButton) - executionGroup.addWidget(self.stopButton) - executionGroup.addWidget(self.nextButton) - # executionGroup.addStretch() # 添加弹性空间 - - # 第二组:管理按钮 - # managementGroup = QHBoxLayout() - # managementGroup.addStretch() # 添加弹性空间 - executionGroup.addWidget(self.resetButton) - executionGroup.addWidget(self.exportButton) - controlLayout.setSpacing(15) - - # 将两组按钮添加到主布局 - controlLayout.addLayout(executionGroup) - # controlLayout.addLayout(managementGroup) + # 添加按钮到布局 + controlLayout.addWidget(self.autoButton) + controlLayout.addWidget(self.stopButton) + controlLayout.addWidget(self.nextButton) + controlLayout.addWidget(self.resetButton) + controlLayout.addWidget(self.exportButton) + # controlLayout.addStretch() # 添加弹性空间,将按钮推到左侧 layout.addLayout(controlLayout) @@ -649,62 +689,7 @@ class StepExecutor(QWidget): step.get('result') and '失败' not in step.get('result', '')) - def adjustRowHeight(self, row): - """调整指定行的高度以适应内容""" - try: - # 获取该行的内容 - stepInfo = self.tableModel.getStepInfo(row) - if not stepInfo: - return - - # 计算需要的行高,确保所有值都不为None - description = stepInfo.get('description') or '' - result = stepInfo.get('result') or '' - note = stepInfo.get('note') or '' - - # 确保所有值都是字符串类型 - if not isinstance(description, str): - description = str(description) if description is not None else '' - if not isinstance(result, str): - result = str(result) if result is not None else '' - if not isinstance(note, str): - note = str(note) if note is not None else '' - - # 基于最长文本计算行高 - max_text_length = max(len(description), len(result), len(note)) - - # 基础行高 - base_height = 35 - - # 根据文本长度动态调整 - if max_text_length > 100: - height = base_height + (max_text_length // 50) * 15 - elif max_text_length > 50: - height = base_height + 15 - else: - height = base_height - - # 设置行高,最大不超过150像素 - height = min(height, 150) - self.tableView.setRowHeight(row, height) - - except Exception as e: - print(f"调整行高时出错: {e}") - - def adjustAllRowHeights(self): - """调整所有行的高度""" - try: - if not hasattr(self, 'tableModel') or self.tableModel is None: - return - - row_count = self.tableModel.rowCount() - if row_count <= 0: - return - - for row in range(row_count): - self.adjustRowHeight(row) - except Exception as e: - print(f"调整所有行高时出错: {e}") + def finishExecution(self): """完成执行""" @@ -793,7 +778,7 @@ class StepExecutor(QWidget): success = self.tableModel.updateStepResult(row, result, datetime.now()) # 更新表格行高以适应内容 - self.adjustRowHeight(row) + self.tableView.adjustRowHeight(row) return result diff --git a/model/ProcedureModel/ProcedureProcessor.py b/model/ProcedureModel/ProcedureProcessor.py index c20f397..6e473d1 100644 --- a/model/ProcedureModel/ProcedureProcessor.py +++ b/model/ProcedureModel/ProcedureProcessor.py @@ -85,205 +85,4 @@ class ExcelParser: "测试步骤": testSteps } -class StepTableModel(QAbstractTableModel): - columns = ['序号', '实验步骤','操作类型', '执行时间', '是否与预期一致', '实际结果', '备注'] - - def __init__(self, testSteps): - super().__init__() - self.stepData = [] - self.stepIndex = 0 - - for mainStep in testSteps: - self.stepData.append({ - 'id': self.stepIndex, - 'isMain': True, - 'stepId': mainStep['步骤ID'], - 'description': mainStep['步骤描述'], - 'executed': False, - 'stepType': mainStep['操作类型'], - 'time': None, - 'result': None, - 'note': mainStep.get('备注', '') # 修复:从主步骤的备注字段读取 - }) - self.stepIndex += 1 - - for subStep in mainStep['子步骤']: - self.stepData.append({ - 'id': self.stepIndex, - 'isMain': False, - 'stepId': f"{mainStep['步骤ID']}{subStep['序号']}", - 'description': subStep['操作'], - 'stepType': subStep['操作类型'], - 'executed': False, - 'time': None, - 'result': None, - 'note': subStep['备注'] # 新增:从Excel解析的备注字段 - }) - self.stepIndex += 1 - - def rowCount(self, parent=QModelIndex()): - return len(self.stepData) - - def columnCount(self, parent=QModelIndex()): - return len(self.columns) - - def data(self, index, role=Qt.DisplayRole): - if not index.isValid(): - return None - - row = index.row() - col = index.column() - step = self.stepData[row] - - if role == Qt.DisplayRole: - if col == 0: - return step['stepId'] or '' - elif col == 1: - return step['description'] or '' - elif col == 2: - return step['stepType'] or '' - elif col == 3: - return step['time'].strftime("%Y-%m-%d %H:%M:%S") if step['time'] else '' - elif col == 4: - # print(step['result']) - if step['executed']: - if '失败' in step['result']: - return '✘' - else: - return '✓' - elif col == 5: - # print(step['result']) - return step['result'] or '' - elif col == 6: - return step['note'] if step['note'] else '' - - elif role == Qt.BackgroundRole: - if step['executed']: - if '失败' in step['result']: - return QBrush(QColor(255, 182, 193)) - else: - return QBrush(QColor(144, 238, 144)) - elif step['isMain']: - return QBrush(QColor(220, 220, 220)) - - elif role == Qt.TextAlignmentRole: - if col in [0, 2, 3, 4]: # 步骤ID、操作类型、执行时间、执行结果居中对齐 - return Qt.AlignCenter - else: # 其他列左对齐并顶部对齐 - return Qt.AlignLeft | Qt.AlignTop - - elif role == Qt.FontRole and step['isMain']: - font = QFont() - font.setBold(True) - return font - - # 新增:支持自动换行 - elif role == Qt.TextAlignmentRole: - if col in [1, 5]: # 描述和备注列 - return Qt.AlignLeft | Qt.AlignVCenter - elif role == Qt.TextWordWrap: - if col in [1, 5]: - return True - - return None - def flags(self, index): - """返回单元格标志""" - flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable - return flags - - def headerData(self, section, orientation, role): - if role == Qt.DisplayRole and orientation == Qt.Horizontal: - return self.columns[section] - return None - - def getStepInfo(self, row): - if 0 <= row < len(self.stepData): - return self.stepData[row] - return None - - def getFullStepInfo(self, row): - """获取完整的步骤信息""" - if 0 <= row < len(self.stepData): - return self.stepData[row] - return None - - def updateStepResult(self, row, result, time): - if 0 <= row < len(self.stepData): - # print(result) - self.stepData[row]['executed'] = True - self.stepData[row]['time'] = time - self.stepData[row]['result'] = result - self.dataChanged.emit(self.index(row, 0), - self.index(row, self.columnCount()-1), - [Qt.DisplayRole, Qt.BackgroundRole]) - return True - return False - - def resetExecutionState(self): - """只重置执行状态(颜色),不清除时间和结果""" - for step in self.stepData: - step['executed'] = False - step['result'] = None - self.dataChanged.emit(self.index(0, 0), - self.index(self.rowCount()-1, self.columnCount()-1), - [Qt.BackgroundRole]) - - def resetAll(self): - """完全重置所有状态(包括时间和结果)""" - for step in self.stepData: - step.update({ - 'executed': False, - 'time': None, - 'result': None - }) - self.dataChanged.emit(self.index(0, 0), - self.index(self.rowCount()-1, self.columnCount()-1), - [Qt.DisplayRole, Qt.BackgroundRole]) - - def getTestSteps(self): - """获取测试步骤数据,用于保存""" - testSteps = [] - currentMainStep = None - - for step in self.stepData: - if step['isMain']: - # 如果有前一个主步骤,先添加到结果中 - if currentMainStep: - testSteps.append(currentMainStep) - - # 创建新的主步骤 - currentMainStep = { - '步骤ID': step['stepId'], - '步骤描述': step['description'], - '操作类型': step['stepType'], - '预期结果': '', - '子步骤': [] - } - else: - # 子步骤 - if currentMainStep: - # 从步骤ID中提取序号 - stepId = step['stepId'] - if currentMainStep['步骤ID'] in stepId: - subStepId = stepId.replace(currentMainStep['步骤ID'], '') - else: - subStepId = stepId - - subStep = { - '序号': subStepId, - '操作': step['description'], - '操作类型': step['stepType'], - '预期结果': '', - '实际结果': step.get('result', ''), - '一致性': '是' if step.get('result') and '失败' not in step.get('result', '') else '否', - '测试时间': step.get('time', ''), - '备注': step.get('note', '') - } - currentMainStep['子步骤'].append(subStep) - - # 添加最后一个主步骤 - if currentMainStep: - testSteps.append(currentMainStep) - - return testSteps