""" 流水线执行对话框 """ from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QTextEdit, QPushButton, QProgressBar, QFrame, QMessageBox ) from PyQt5.QtCore import Qt, QTimer from datetime import datetime class PipelineDialog(QDialog): """流水线执行对话框""" def __init__(self, project, parent=None): """ 初始化对话框 Args: project: 项目对象 parent: 父窗口 """ super().__init__(parent) self.project = project self.current_step = 0 self.timer = None self._setup_ui() def _setup_ui(self): """设置UI""" self.setWindowTitle(f"流水线 - {self.project.name}") self.resize(1000, 600) layout = QVBoxLayout(self) layout.setSpacing(15) # 标题 title_label = QLabel(f"

🚀 项目流水线 - {self.project.name}

") layout.addWidget(title_label) # 流水线步骤 steps_layout = QHBoxLayout() steps_layout.setSpacing(10) self.step_widgets = [] steps = [ ("🔍", "静态扫描", "SonarQube"), ("🔨", "编译构建", "Maven"), ("📦", "打包", "JAR"), ("🚀", "部署", "测试环境"), ("✅", "验证测试", "JUnit") ] for icon, name, tool in steps: step_widget = self._create_step_widget(icon, name, tool) self.step_widgets.append(step_widget) steps_layout.addWidget(step_widget) layout.addLayout(steps_layout) # 日志输出区域 log_label = QLabel("执行日志:") layout.addWidget(log_label) self.log_text = QTextEdit() self.log_text.setReadOnly(True) self.log_text.setStyleSheet(""" QTextEdit { background: #1e293b; color: #10b981; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 12px; border: 1px solid rgba(59, 130, 246, 0.2); border-radius: 8px; padding: 10px; } """) layout.addWidget(self.log_text) # 总体进度条 self.progress = QProgressBar() self.progress.setTextVisible(True) self.progress.setFormat("%p%") layout.addWidget(self.progress) # 按钮区域 button_layout = QHBoxLayout() button_layout.addStretch() self.start_btn = QPushButton("▶ 启动流水线") self.start_btn.setStyleSheet(""" QPushButton { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #10b981, stop:1 #059669); } """) self.start_btn.setMinimumWidth(120) self.start_btn.clicked.connect(self._start_pipeline) button_layout.addWidget(self.start_btn) self.stop_btn = QPushButton("⏹ 停止") self.stop_btn.setStyleSheet(""" QPushButton { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ef4444, stop:1 #dc2626); } """) self.stop_btn.setMinimumWidth(120) self.stop_btn.setEnabled(False) self.stop_btn.clicked.connect(self._stop_pipeline) button_layout.addWidget(self.stop_btn) close_btn = QPushButton("关闭") close_btn.setMinimumWidth(120) close_btn.clicked.connect(self.accept) button_layout.addWidget(close_btn) layout.addLayout(button_layout) def _create_step_widget(self, icon: str, name: str, tool: str) -> QFrame: """创建步骤组件""" widget = QFrame() widget.setFrameShape(QFrame.StyledPanel) widget.setStyleSheet(""" QFrame { background: rgba(51, 65, 85, 0.4); border: 1px solid rgba(59, 130, 246, 0.2); border-radius: 8px; padding: 15px; } """) layout = QVBoxLayout(widget) layout.setAlignment(Qt.AlignCenter) layout.setSpacing(8) # 图标 icon_label = QLabel(icon) icon_label.setStyleSheet("font-size: 36px;") icon_label.setAlignment(Qt.AlignCenter) layout.addWidget(icon_label) # 步骤名称 name_label = QLabel(name) name_label.setStyleSheet(""" font-weight: bold; font-size: 14px; color: #e0e6ed; """) name_label.setAlignment(Qt.AlignCenter) layout.addWidget(name_label) # 工具名称 tool_label = QLabel(tool) tool_label.setStyleSheet(""" color: #94a3b8; font-size: 11px; """) tool_label.setAlignment(Qt.AlignCenter) layout.addWidget(tool_label) # 状态标签 status_label = QLabel("就绪") status_label.setObjectName("status_label") status_label.setStyleSheet(""" color: #94a3b8; font-size: 12px; """) status_label.setAlignment(Qt.AlignCenter) layout.addWidget(status_label) return widget def _start_pipeline(self): """启动流水线""" self.start_btn.setEnabled(False) self.stop_btn.setEnabled(True) self.current_step = 0 self.progress.setValue(0) self.log_text.clear() self._add_log("[INFO] ========================================") self._add_log(f"[INFO] 流水线启动 - 项目: {self.project.name}") self._add_log("[INFO] ========================================") # 使用定时器模拟流水线执行 self.timer = QTimer() self.timer.timeout.connect(self._update_pipeline) self.timer.start(1500) # 每1.5秒执行一步 def _update_pipeline(self): """更新流水线状态""" if self.current_step < len(self.step_widgets): widget = self.step_widgets[self.current_step] # 更新为进行中状态 widget.setStyleSheet(""" QFrame { background: rgba(59, 130, 246, 0.3); border: 2px solid #3b82f6; border-radius: 8px; padding: 15px; } """) # 更新状态标签 status_label = widget.findChild(QLabel, "status_label") if status_label: status_label.setText("进行中...") status_label.setStyleSheet(""" color: #3b82f6; font-size: 12px; font-weight: bold; """) # 添加日志 step_names = ["静态扫描", "编译构建", "打包", "部署", "验证测试"] self._add_log(f"[INFO] 开始执行: {step_names[self.current_step]}") self._add_log(f"[INFO] 步骤 {self.current_step + 1}/{len(self.step_widgets)}") # 更新进度条 progress_value = int((self.current_step + 1) / len(self.step_widgets) * 100) self.progress.setValue(progress_value) # 延迟标记为完成 QTimer.singleShot(1000, lambda: self._complete_step(self.current_step)) self.current_step += 1 else: self.timer.stop() self._finish_pipeline() def _complete_step(self, step_index: int): """完成步骤""" if step_index < len(self.step_widgets): widget = self.step_widgets[step_index] # 更新为完成状态 widget.setStyleSheet(""" QFrame { background: rgba(16, 185, 129, 0.2); border: 2px solid #10b981; border-radius: 8px; padding: 15px; } """) # 更新状态标签 status_label = widget.findChild(QLabel, "status_label") if status_label: status_label.setText("✓ 完成") status_label.setStyleSheet(""" color: #10b981; font-size: 12px; font-weight: bold; """) # 添加完成日志 step_names = ["静态扫描", "编译构建", "打包", "部署", "验证测试"] self._add_log(f"[SUCCESS] {step_names[step_index]} 完成") self._add_log("") def _finish_pipeline(self): """完成流水线""" self._add_log("[INFO] ========================================") self._add_log("[SUCCESS] 流水线执行完成!") self._add_log(f"[INFO] 项目: {self.project.name}") self._add_log("[INFO] 所有步骤已成功执行") self._add_log("[INFO] ========================================") self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) QMessageBox.information( self, "完成", f"流水线执行完成!\n\n项目: {self.project.name}\n所有步骤已成功执行。" ) def _stop_pipeline(self): """停止流水线""" if self.timer: self.timer.stop() self._add_log("") self._add_log("[WARNING] ========================================") self._add_log("[WARNING] 流水线已被用户停止") self._add_log("[WARNING] ========================================") self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) def _add_log(self, message: str): """添加日志""" timestamp = datetime.now().strftime("%H:%M:%S") self.log_text.append(f"[{timestamp}] {message}") # 自动滚动到底部 scrollbar = self.log_text.verticalScrollBar() scrollbar.setValue(scrollbar.maximum())