文件预览

progress_display.py

查看 EvoMap WorkBench v1.0.11 Mini 技能包中的文件内容。

文件内容

lib/progress_display.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
进度显示 - 完整版
功能:进度条、时间统计、阶段管理
"""

from datetime import datetime
from typing import Optional, Dict, List
import sys
import time


class ProgressDisplay:
    """进度显示类"""
    
    ICONS = {
        "waiting": "⏳",
        "running": "🔄",
        "success": "✅",
        "error": "❌",
        "warning": "⚠️",
        "info": "ℹ️"
    }
    
    def __init__(self, show_timestamp: bool = True, show_progress_bar: bool = True):
        self.show_timestamp = show_timestamp
        self.show_progress_bar = show_progress_bar
        self.current_stage = None
        self.stage_count = 0
        self.current_stage_num = 0
        self.start_time = None
        self.stage_times: Dict[int, float] = {}
    
    def _timestamp(self) -> str:
        """获取时间戳字符串"""
        if self.show_timestamp:
            return datetime.now().strftime("%H:%M:%S")
        return ""
    
    def _print(self, icon: str, message: str):
        """打印消息"""
        ts = self._timestamp()
        if ts:
            print(f"[{ts}] {icon} {message}")
        else:
            print(f"{icon} {message}")
        sys.stdout.flush()
    
    def _render_progress_bar(self, current: int, total: int, width: int = 50) -> str:
        """渲染进度条"""
        if not self.show_progress_bar:
            return ""
        
        percent = current / total if total > 0 else 0
        filled = int(width * percent)
        bar = "█" * filled + "░" * (width - filled)
        return f"[{bar}] {percent:.1%}"
    
    def start(self, total_stages: int, title: str = "EvoMap WorkBench"):
        """开始任务"""
        self.stage_count = total_stages
        self.current_stage_num = 0
        self.start_time = time.time()
        self.stage_times = {}
        
        print("=" * 70)
        print(f"🚀 {title}")
        print("=" * 70)
        print(f"📋 总阶段:{total_stages}")
        print(f"🕐 开始时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 70)
        print()
    
    def stage(self, stage_num: int, name: str, message: Optional[str] = None):
        """显示阶段开始"""
        self.current_stage_num = stage_num
        self.current_stage = name
        self.stage_times[stage_num] = time.time()
        
        progress = f"[{stage_num}/{self.stage_count}]"
        
        if self.show_progress_bar:
            bar = self._render_progress_bar(stage_num, self.stage_count)
            self._print(self.ICONS["running"], f"{progress} {name} {bar}")
        else:
            self._print(self.ICONS["running"], f"{progress} {name}")
        
        if message:
            print(f"   {message}")
            print()
    
    def stage_success(self, message: Optional[str] = None, duration: Optional[float] = None):
        """显示阶段成功"""
        extra = ""
        
        if duration:
            extra = f" (耗时:{duration:.1f}s)"
        elif self.current_stage_num in self.stage_times:
            duration = time.time() - self.stage_times[self.current_stage_num]
            extra = f" (耗时:{duration:.1f}s)"
        
        if message:
            extra = f" - {message}{extra}"
        
        self._print(self.ICONS["success"], f"{self.current_stage} 完成{extra}")
        print()
    
    def stage_error(self, error: str, recoverable: bool = True):
        """显示阶段错误"""
        status = "可恢复" if recoverable else "致命"
        self._print(self.ICONS["error"], f"{self.current_stage} 失败 [{status}]")
        print(f"   错误:{error}")
        print()
    
    def stage_warning(self, warning: str):
        """显示阶段警告"""
        self._print(self.ICONS["warning"], f"{self.current_stage} 警告")
        print(f"   {warning}")
        print()
    
    def info(self, message: str):
        """显示信息"""
        self._print(self.ICONS["info"], message)
    
    def finish(self, success: bool, summary: Dict):
        """显示任务完成"""
        print()
        print("=" * 70)
        
        if success:
            self._print(self.ICONS["success"], "任务完成")
        else:
            self._print(self.ICONS["error"], "任务失败")
        
        print()
        print("📊 执行汇总:")
        for key, value in summary.items():
            print(f"   {key}: {value}")
        
        if self.start_time:
            total_duration = time.time() - self.start_time
            print(f"   总耗时:{total_duration:.1f}s")
            print(f"   平均阶段耗时:{total_duration/self.stage_count:.1f}s" if self.stage_count > 0 else "")
        
        print()
        print(f"🕐 结束时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 70)
    
    def get_elapsed_time(self) -> float:
        """获取已用时间"""
        if self.start_time:
            return time.time() - self.start_time
        return 0.0
    
    def get_stage_elapsed_time(self, stage_num: int) -> float:
        """获取阶段已用时间"""
        if stage_num in self.stage_times:
            return time.time() - self.stage_times[stage_num]
        return 0.0


class PublishProgress(ProgressDisplay):
    """发布进度显示"""
    
    def __init__(self):
        super().__init__(show_timestamp=True, show_progress_bar=True)
    
    def start_publish(self, task_count: int):
        """开始发布"""
        self.start(4 + task_count, "EvoMap 资产发布")
    
    def hello_auth(self):
        """Hello 认证"""
        self.stage(1, "Hello 认证")
    
    def validate_assets(self, count: int):
        """验证资产"""
        self.stage(2, f"验证资产 ({count}个)")
    
    def dry_run(self):
        """Dry-Run 验证"""
        self.stage(3, "发布前验证")
    
    def publish_task(self, task_name: str, index: int):
        """发布任务"""
        self.stage(3 + index, f"发布:{task_name}")
    
    def generate_report(self):
        """生成报告"""
        self.stage(-1, "生成报告")


if __name__ == "__main__":
    # 测试进度显示
    progress = PublishProgress()
    progress.start_publish(3)
    
    progress.hello_auth()
    time.sleep(0.5)
    progress.stage_success("认证成功")
    
    progress.validate_assets(4)
    time.sleep(0.3)
    progress.stage_success("验证通过")
    
    progress.dry_run()
    time.sleep(0.3)
    progress.stage_success("Dry-Run 通过")
    
    for i in range(3):
        progress.publish_task(f"task-{i}", i + 1)
        time.sleep(0.5)
        progress.stage_success("发布成功")
    
    progress.generate_report()
    progress.finish(True, {
        "总任务数": 3,
        "成功": 3,
        "失败": 0
    })