fscan/Common/ProgressManager.go
ZacharyZcR 2f9c213e80 refactor: 系统性清理common包中的死代码和未使用变量
主要清理内容:
- logging包:移除DetailedFormatter、JSONFormatter及相关方法
- output包:清理Manager和Statistics中的未使用方法
- parsers包:移除各Parser中的Validate()和GetStatistics()方法
- proxy包:清理Factory和Global中的所有未使用函数
- ProgressManager:移除未使用的进度条方法和字段
- globals:清理未使用的status变量

技术改进:
- 使用deadcode和golangci-lint工具系统性检测
- 保持代码结构清晰,添加清理注释
- 修复相关依赖引用问题
- 确保编译通过和功能正常

代码减少:移除约40个死代码函数和多个未使用字段
2025-08-06 08:14:00 +08:00

318 lines
7.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"fmt"
"os"
"sync"
"time"
"github.com/shadow1ng/fscan/common/i18n"
)
/*
ProgressManager.go - 固定底部进度条管理器
提供固定在终端底部的进度条显示,与正常输出内容分离。
使用终端控制码实现位置固定和内容保护。
*/
// ProgressManager 进度条管理器
type ProgressManager struct {
mu sync.RWMutex
enabled bool
total int64
current int64
description string
startTime time.Time
isActive bool
terminalHeight int
reservedLines int // 为进度条保留的行数
lastContentLine int // 最后一行内容的位置
// 输出缓冲相关
outputMutex sync.Mutex
}
var (
globalProgressManager *ProgressManager
progressMutex sync.Mutex
)
// GetProgressManager 获取全局进度条管理器
func GetProgressManager() *ProgressManager {
progressMutex.Lock()
defer progressMutex.Unlock()
if globalProgressManager == nil {
globalProgressManager = &ProgressManager{
enabled: true,
reservedLines: 2, // 保留2行进度条 + 空行
terminalHeight: getTerminalHeight(),
}
}
return globalProgressManager
}
// InitProgress 初始化进度条
func (pm *ProgressManager) InitProgress(total int64, description string) {
if !ShowProgress || Silent {
pm.enabled = false
return
}
pm.mu.Lock()
defer pm.mu.Unlock()
pm.total = total
pm.current = 0
pm.description = description
pm.startTime = time.Now()
pm.isActive = true
pm.enabled = true
// 为进度条保留空间
pm.setupProgressSpace()
// 初始显示进度条
pm.renderProgress()
}
// UpdateProgress 更新进度
func (pm *ProgressManager) UpdateProgress(increment int64) {
if !pm.enabled || !pm.isActive {
return
}
pm.mu.Lock()
defer pm.mu.Unlock()
pm.current += increment
if pm.current > pm.total {
pm.current = pm.total
}
pm.renderProgress()
}
// =============================================================================================
// 已删除的死代码未使用SetProgress 设置当前进度
// =============================================================================================
// FinishProgress 完成进度条
func (pm *ProgressManager) FinishProgress() {
if !pm.enabled || !pm.isActive {
return
}
pm.mu.Lock()
defer pm.mu.Unlock()
pm.current = pm.total
pm.renderProgress()
// 显示完成信息
pm.showCompletionInfo()
// 清理进度条区域,恢复正常输出
pm.clearProgressArea()
pm.isActive = false
}
// setupProgressSpace 设置进度条空间
func (pm *ProgressManager) setupProgressSpace() {
// 简化设计:进度条在原地更新,不需要预留额外空间
// 只是标记进度条开始的位置
pm.lastContentLine = 0
}
// =============================================================================================
// 已删除的死代码未使用moveToContentArea 和 moveToProgressLine 方法
// =============================================================================================
// renderProgress 渲染进度条(使用锁避免输出冲突)
func (pm *ProgressManager) renderProgress() {
pm.outputMutex.Lock()
defer pm.outputMutex.Unlock()
pm.renderProgressUnsafe()
}
// generateProgressBar 生成进度条字符串
func (pm *ProgressManager) generateProgressBar() string {
if pm.total == 0 {
return fmt.Sprintf("%s: 等待中...", pm.description)
}
percentage := float64(pm.current) / float64(pm.total) * 100
elapsed := time.Since(pm.startTime)
// 计算预估剩余时间
var eta string
if pm.current > 0 {
totalTime := elapsed * time.Duration(pm.total) / time.Duration(pm.current)
remaining := totalTime - elapsed
if remaining > 0 {
eta = fmt.Sprintf(" ETA:%s", formatDuration(remaining))
}
}
// 计算速度
speed := float64(pm.current) / elapsed.Seconds()
speedStr := ""
if speed > 0 {
speedStr = fmt.Sprintf(" (%.1f/s)", speed)
}
// 生成进度条
barWidth := 30
filled := int(percentage * float64(barWidth) / 100)
bar := ""
if NoColor {
// 无颜色版本
bar = "[" +
fmt.Sprintf("%s%s",
string(make([]rune, filled)),
string(make([]rune, barWidth-filled))) +
"]"
for i := 0; i < filled; i++ {
bar = bar[:i+1] + "=" + bar[i+2:]
}
for i := filled; i < barWidth; i++ {
bar = bar[:i+1] + "-" + bar[i+2:]
}
} else {
// 彩色版本
bar = "|"
for i := 0; i < barWidth; i++ {
if i < filled {
bar += "#"
} else {
bar += "."
}
}
bar += "|"
}
return fmt.Sprintf("%s %6.1f%% %s (%d/%d)%s%s",
pm.description, percentage, bar, pm.current, pm.total, speedStr, eta)
}
// showCompletionInfo 显示完成信息
func (pm *ProgressManager) showCompletionInfo() {
elapsed := time.Since(pm.startTime)
// 换行并显示完成信息
fmt.Print("\n")
completionMsg := i18n.GetText("progress_scan_completed")
if NoColor {
fmt.Printf("[完成] %s %d/%d (耗时: %s)\n",
completionMsg, pm.total, pm.total, formatDuration(elapsed))
} else {
fmt.Printf("\033[32m[完成] %s %d/%d\033[0m \033[90m(耗时: %s)\033[0m\n",
completionMsg, pm.total, pm.total, formatDuration(elapsed))
}
}
// clearProgressArea 清理进度条区域
func (pm *ProgressManager) clearProgressArea() {
// 简单清除当前行
fmt.Print("\033[2K\r")
}
// IsActive 检查进度条是否活跃
func (pm *ProgressManager) IsActive() bool {
pm.mu.RLock()
defer pm.mu.RUnlock()
return pm.isActive && pm.enabled
}
// getTerminalHeight 获取终端高度
func getTerminalHeight() int {
// 对于固定底部进度条,我们暂时禁用终端高度检测
// 因为在不同终端环境中可能会有问题
// 改为使用相对定位方式
return 0 // 返回0表示使用简化模式
}
// formatDuration 格式化时间间隔
func formatDuration(d time.Duration) string {
if d < time.Minute {
return fmt.Sprintf("%.1fs", d.Seconds())
} else if d < time.Hour {
return fmt.Sprintf("%.1fm", d.Minutes())
} else {
return fmt.Sprintf("%.1fh", d.Hours())
}
}
// 全局函数,方便其他模块调用
func InitProgressBar(total int64, description string) {
GetProgressManager().InitProgress(total, description)
}
func UpdateProgressBar(increment int64) {
GetProgressManager().UpdateProgress(increment)
}
// =============================================================================================
// 已删除的死代码未使用SetProgressBar 全局函数
// =============================================================================================
func FinishProgressBar() {
GetProgressManager().FinishProgress()
}
func IsProgressActive() bool {
return GetProgressManager().IsActive()
}
// =============================================================================
// 日志输出协调功能
// =============================================================================
// LogWithProgress 在进度条活跃时协调日志输出
func LogWithProgress(message string) {
pm := GetProgressManager()
if !pm.IsActive() {
// 如果进度条不活跃,直接输出
fmt.Println(message)
return
}
pm.outputMutex.Lock()
defer pm.outputMutex.Unlock()
// 清除当前行(清除进度条)
fmt.Print("\033[2K\r")
// 输出日志消息
fmt.Println(message)
// 重绘进度条
pm.renderProgressUnsafe()
}
// renderProgressUnsafe 不加锁的进度条渲染(内部使用)
func (pm *ProgressManager) renderProgressUnsafe() {
if !pm.enabled || !pm.isActive {
return
}
// 移动到行首并清除当前行
fmt.Print("\033[2K\r")
// 生成进度条内容
progressBar := pm.generateProgressBar()
// 输出进度条(带颜色,如果启用)
if NoColor {
fmt.Print(progressBar)
} else {
fmt.Printf("\033[36m%s\033[0m", progressBar) // 青色
}
// 刷新输出
os.Stdout.Sync()
}