UNPKG

@xuanqikai/one-click-upload

Version:

A CLI tool for one-click file upload to cloud storage services (OSS, TOS)

214 lines 6.81 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BatchProgress = exports.SimpleProgress = exports.ProgressBar = void 0; const chalk_1 = __importDefault(require("chalk")); const fileUtils_1 = require("./fileUtils"); class ProgressBar { constructor(options = {}) { this.speeds = []; this.maxSpeedSamples = 10; this.options = { width: 40, showPercentage: true, showSpeed: true, showETA: true, showFileInfo: true, ...options }; this.startTime = Date.now(); this.lastUpdate = this.startTime; this.lastLoaded = 0; } /** * 更新进度 */ update(progress) { const now = Date.now(); const timeDiff = now - this.lastUpdate; // 计算速度(每秒字节数) if (timeDiff > 0) { const bytesDiff = progress.loaded - this.lastLoaded; const speed = (bytesDiff / timeDiff) * 1000; // bytes per second this.speeds.push(speed); if (this.speeds.length > this.maxSpeedSamples) { this.speeds.shift(); } this.lastUpdate = now; this.lastLoaded = progress.loaded; } return this.render(progress); } /** * 渲染进度条 */ render(progress) { const { loaded, total, percentage, fileName } = progress; let output = ''; // 文件信息 if (this.options.showFileInfo && fileName) { output += chalk_1.default.cyan(`${fileName}\n`); } // 进度条 const progressBar = this.renderProgressBar(percentage); output += progressBar; // 百分比 if (this.options.showPercentage) { output += ` ${percentage.toFixed(1)}%`; } // 文件大小信息 output += ` ${(0, fileUtils_1.formatFileSize)(loaded)}/${(0, fileUtils_1.formatFileSize)(total)}`; // 速度 if (this.options.showSpeed) { const speed = this.calculateAverageSpeed(); if (speed > 0) { output += ` ${(0, fileUtils_1.formatFileSize)(speed)}/s`; } } // 预计剩余时间 if (this.options.showETA && total > loaded) { const eta = this.calculateETA(loaded, total); if (eta > 0) { output += ` ETA: ${(0, fileUtils_1.formatDuration)(eta)}`; } } return output; } /** * 渲染进度条图形 */ renderProgressBar(percentage) { const { width } = this.options; const filled = Math.round((percentage / 100) * width); const empty = width - filled; const filledBar = '█'.repeat(filled); const emptyBar = '░'.repeat(empty); return chalk_1.default.green(filledBar) + chalk_1.default.gray(emptyBar); } /** * 计算平均速度 */ calculateAverageSpeed() { if (this.speeds.length === 0) return 0; const sum = this.speeds.reduce((a, b) => a + b, 0); return sum / this.speeds.length; } /** * 计算预计剩余时间 */ calculateETA(loaded, total) { const speed = this.calculateAverageSpeed(); if (speed <= 0) return 0; const remaining = total - loaded; return (remaining / speed) * 1000; // 转换为毫秒 } /** * 重置进度条 */ reset() { this.startTime = Date.now(); this.lastUpdate = this.startTime; this.lastLoaded = 0; this.speeds = []; } } exports.ProgressBar = ProgressBar; /** * 简单的进度显示器 */ class SimpleProgress { constructor() { this.lastPercentage = -1; } /** * 显示进度 */ show(progress) { const { percentage, fileName } = progress; // 只在百分比变化时更新显示 if (Math.floor(percentage) !== this.lastPercentage) { this.lastPercentage = Math.floor(percentage); const bar = this.createSimpleBar(percentage); const info = fileName ? `${fileName} - ` : ''; process.stdout.write(`\r${info}${bar} ${percentage.toFixed(1)}%`); if (percentage >= 100) { process.stdout.write('\n'); } } } /** * 创建简单的进度条 */ createSimpleBar(percentage, width = 20) { const filled = Math.round((percentage / 100) * width); const empty = width - filled; return `[${'='.repeat(filled)}${' '.repeat(empty)}]`; } /** * 清除当前行 */ clear() { process.stdout.write('\r' + ' '.repeat(80) + '\r'); } } exports.SimpleProgress = SimpleProgress; /** * 批量上传进度显示器 */ class BatchProgress { constructor(totalFiles) { this.currentFile = 0; this.totalFiles = 0; this.fileProgress = new Map(); this.totalFiles = totalFiles; } /** * 更新文件进度 */ updateFile(fileIndex, progress) { this.fileProgress.set(fileIndex, progress); this.currentFile = Math.max(this.currentFile, fileIndex); this.render(); } /** * 渲染批量进度 */ render() { // 计算总体进度 let totalLoaded = 0; let totalSize = 0; for (const progress of this.fileProgress.values()) { totalLoaded += progress.loaded; totalSize += progress.total; } const overallPercentage = totalSize > 0 ? (totalLoaded / totalSize) * 100 : 0; // 获取当前文件进度 const currentProgress = this.fileProgress.get(this.currentFile); const currentFileName = currentProgress?.fileName || 'Unknown'; const currentPercentage = currentProgress?.percentage || 0; // 清除当前行并显示新进度 process.stdout.write('\r' + ' '.repeat(100) + '\r'); const output = [ `Files: ${this.currentFile + 1}/${this.totalFiles}`, `Overall: ${overallPercentage.toFixed(1)}%`, `Current: ${currentFileName} (${currentPercentage.toFixed(1)}%)` ].join(' | '); process.stdout.write(output); if (overallPercentage >= 100) { process.stdout.write('\n'); } } /** * 完成显示 */ complete() { process.stdout.write('\n'); console.log(chalk_1.default.green('✓ All files uploaded successfully')); } } exports.BatchProgress = BatchProgress; //# sourceMappingURL=progressBar.js.map