pcu 0.5.3 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +87 -0
- package/README.md +69 -16
- package/README.zh-CN.md +17 -8
- package/dist/application/services/CatalogUpdateService.d.ts.map +1 -1
- package/dist/application/services/CatalogUpdateService.js +47 -28
- package/dist/application/services/CatalogUpdateService.js.map +1 -1
- package/dist/cli/commands/CheckCommand.d.ts.map +1 -1
- package/dist/cli/commands/CheckCommand.js +0 -13
- package/dist/cli/commands/CheckCommand.js.map +1 -1
- package/dist/cli/commands/InitCommand.d.ts +53 -0
- package/dist/cli/commands/InitCommand.d.ts.map +1 -0
- package/dist/cli/commands/InitCommand.js +338 -0
- package/dist/cli/commands/InitCommand.js.map +1 -0
- package/dist/cli/commands/SecurityCommand.d.ts.map +1 -1
- package/dist/cli/commands/SecurityCommand.js +0 -2
- package/dist/cli/commands/SecurityCommand.js.map +1 -1
- package/dist/cli/commands/UpdateCommand.d.ts.map +1 -1
- package/dist/cli/commands/UpdateCommand.js +20 -27
- package/dist/cli/commands/UpdateCommand.js.map +1 -1
- package/dist/cli/formatters/ProgressBar.d.ts +13 -27
- package/dist/cli/formatters/ProgressBar.d.ts.map +1 -1
- package/dist/cli/formatters/ProgressBar.js +113 -147
- package/dist/cli/formatters/ProgressBar.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +32 -3
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Supports interactive mode, dry-run, and various update strategies.
|
|
6
6
|
*/
|
|
7
7
|
import { OutputFormatter } from '../formatters/OutputFormatter.js';
|
|
8
|
-
import { ProgressBar
|
|
8
|
+
import { ProgressBar } from '../formatters/ProgressBar.js';
|
|
9
9
|
import { InteractivePrompts } from '../interactive/InteractivePrompts.js';
|
|
10
10
|
import { StyledText, ThemeManager } from '../themes/ColorTheme.js';
|
|
11
11
|
import { ConfigLoader } from '../../common/config/ConfigLoader.js';
|
|
@@ -18,16 +18,16 @@ export class UpdateCommand {
|
|
|
18
18
|
* Execute the update command
|
|
19
19
|
*/
|
|
20
20
|
async execute(options = {}) {
|
|
21
|
-
const multiStep = new MultiStepProgress([
|
|
22
|
-
'Loading workspace configuration',
|
|
23
|
-
'Checking package versions',
|
|
24
|
-
'Planning updates',
|
|
25
|
-
'Applying updates',
|
|
26
|
-
]);
|
|
27
21
|
let progressBar;
|
|
28
22
|
try {
|
|
29
23
|
// Initialize theme
|
|
30
24
|
ThemeManager.setTheme('default');
|
|
25
|
+
// Create progress bar for the update process
|
|
26
|
+
progressBar = new ProgressBar({
|
|
27
|
+
text: '正在规划更新...',
|
|
28
|
+
total: 4, // 4 main steps
|
|
29
|
+
});
|
|
30
|
+
progressBar.start('正在加载工作区配置...');
|
|
31
31
|
// Load configuration file first
|
|
32
32
|
const config = ConfigLoader.loadConfig(options.workspace || process.cwd());
|
|
33
33
|
// Use format from CLI options first, then config file, then default
|
|
@@ -48,54 +48,47 @@ export class UpdateCommand {
|
|
|
48
48
|
force: options.force ?? false,
|
|
49
49
|
createBackup: options.createBackup ?? config.defaults?.createBackup ?? false,
|
|
50
50
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
progressBar = new ProgressBar({
|
|
54
|
-
text: 'Loading workspace configuration...',
|
|
55
|
-
color: 'cyan',
|
|
56
|
-
spinner: 'dots',
|
|
57
|
-
});
|
|
58
|
-
progressBar.start();
|
|
59
|
-
multiStep.next('Loading workspace configuration');
|
|
51
|
+
// Step 1: Planning updates
|
|
52
|
+
progressBar.update('正在检查包版本...', 1, 4);
|
|
60
53
|
const plan = await this.updateService.planUpdates(updateOptions);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
multiStep.next('Checking package versions');
|
|
54
|
+
// Step 2: Check if any updates found
|
|
55
|
+
progressBar.update('正在分析更新...', 2, 4);
|
|
64
56
|
if (!plan.updates.length) {
|
|
65
|
-
|
|
57
|
+
progressBar.succeed('所有依赖包都是最新的');
|
|
66
58
|
console.log(StyledText.iconSuccess('All dependencies are up to date!'));
|
|
67
59
|
return;
|
|
68
60
|
}
|
|
69
|
-
// Step 3: Planning updates
|
|
70
|
-
multiStep.next('Planning updates');
|
|
71
61
|
console.log(StyledText.iconPackage(`Found ${plan.totalUpdates} update${plan.totalUpdates === 1 ? '' : 's'} available`));
|
|
72
62
|
// Interactive selection if enabled
|
|
73
63
|
let finalPlan = plan;
|
|
74
64
|
if (options.interactive) {
|
|
75
65
|
finalPlan = await this.interactiveSelection(plan);
|
|
76
66
|
if (!finalPlan.updates.length) {
|
|
67
|
+
progressBar.warn('未选择任何更新');
|
|
77
68
|
console.log(StyledText.iconWarning('No updates selected'));
|
|
78
69
|
return;
|
|
79
70
|
}
|
|
80
71
|
}
|
|
81
|
-
// Step
|
|
72
|
+
// Step 3: Apply updates
|
|
73
|
+
progressBar.update('正在准备应用更新...', 3, 4);
|
|
82
74
|
if (!options.dryRun) {
|
|
83
|
-
|
|
75
|
+
// Replace the progress bar with one for applying updates
|
|
76
|
+
progressBar.stop();
|
|
84
77
|
progressBar = new ProgressBar({
|
|
85
78
|
text: 'Applying updates...',
|
|
86
|
-
color: 'green',
|
|
87
79
|
total: finalPlan.updates.length,
|
|
88
80
|
});
|
|
89
|
-
progressBar.start();
|
|
81
|
+
progressBar.start('正在应用更新...');
|
|
90
82
|
const result = await this.updateService.executeUpdates(finalPlan, updateOptions);
|
|
91
83
|
progressBar.succeed(`Applied ${finalPlan.updates.length} updates`);
|
|
92
84
|
console.log(formatter.formatUpdateResult(result));
|
|
93
85
|
}
|
|
94
86
|
else {
|
|
87
|
+
progressBar.update('正在生成预览...', 4, 4);
|
|
88
|
+
progressBar.succeed('更新预览完成');
|
|
95
89
|
console.log(StyledText.iconInfo('Dry run - no changes made'));
|
|
96
90
|
console.log(JSON.stringify(finalPlan, null, 2));
|
|
97
91
|
}
|
|
98
|
-
multiStep.complete();
|
|
99
92
|
console.log(StyledText.iconComplete('Update process completed!'));
|
|
100
93
|
}
|
|
101
94
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpdateCommand.js","sourceRoot":"","sources":["../../../src/cli/commands/UpdateCommand.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAgB,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"UpdateCommand.js","sourceRoot":"","sources":["../../../src/cli/commands/UpdateCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,50 +6,23 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export interface ProgressBarOptions {
|
|
8
8
|
text?: string;
|
|
9
|
-
color?: string;
|
|
10
|
-
spinner?: string;
|
|
11
9
|
total?: number;
|
|
12
10
|
style?: 'default' | 'gradient' | 'fancy' | 'minimal' | 'rainbow' | 'neon';
|
|
13
|
-
width?: number;
|
|
14
|
-
showPercentage?: boolean;
|
|
15
11
|
showSpeed?: boolean;
|
|
16
12
|
}
|
|
17
13
|
export declare class ProgressBar {
|
|
18
|
-
private readonly options;
|
|
19
|
-
private spinner;
|
|
20
14
|
private percentageBar;
|
|
21
15
|
private current;
|
|
22
16
|
private total;
|
|
23
17
|
private text;
|
|
24
18
|
private startTime;
|
|
25
19
|
private style;
|
|
26
|
-
private showPercentage;
|
|
27
20
|
private showSpeed;
|
|
28
21
|
constructor(options?: ProgressBarOptions);
|
|
29
22
|
/**
|
|
30
23
|
* Start the progress bar
|
|
31
24
|
*/
|
|
32
25
|
start(text?: string): void;
|
|
33
|
-
/**
|
|
34
|
-
* Get spinner configuration based on style
|
|
35
|
-
*/
|
|
36
|
-
private getSpinnerConfig;
|
|
37
|
-
/**
|
|
38
|
-
* Get styled text with decorations
|
|
39
|
-
*/
|
|
40
|
-
private getStyledText;
|
|
41
|
-
/**
|
|
42
|
-
* Get styled percentage based on progress
|
|
43
|
-
*/
|
|
44
|
-
private getStyledPercentage;
|
|
45
|
-
/**
|
|
46
|
-
* Get styled progress counter
|
|
47
|
-
*/
|
|
48
|
-
private getStyledProgress;
|
|
49
|
-
/**
|
|
50
|
-
* Apply text styling based on theme
|
|
51
|
-
*/
|
|
52
|
-
private applyTextStyle;
|
|
53
26
|
/**
|
|
54
27
|
* Update progress with text
|
|
55
28
|
*/
|
|
@@ -110,6 +83,10 @@ export declare class ProgressBar {
|
|
|
110
83
|
* Stop the progress bar
|
|
111
84
|
*/
|
|
112
85
|
stop(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Clear previous output to prevent residual progress bars
|
|
88
|
+
*/
|
|
89
|
+
private clearPreviousOutput;
|
|
113
90
|
/**
|
|
114
91
|
* Create a multi-step progress indicator
|
|
115
92
|
*/
|
|
@@ -159,15 +136,24 @@ export declare class PercentageProgressBar {
|
|
|
159
136
|
private lastRender;
|
|
160
137
|
private startTime;
|
|
161
138
|
private style;
|
|
139
|
+
private useMultiLine;
|
|
140
|
+
private isFirstRender;
|
|
162
141
|
constructor(width?: number, options?: {
|
|
163
142
|
style?: string;
|
|
164
143
|
showStats?: boolean;
|
|
144
|
+
multiLine?: boolean;
|
|
165
145
|
});
|
|
166
146
|
start(total: number, text: string): void;
|
|
147
|
+
/**
|
|
148
|
+
* Clear any previous output lines to prevent conflicts
|
|
149
|
+
*/
|
|
150
|
+
private clearPreviousLines;
|
|
167
151
|
update(current: number, text?: string): void;
|
|
168
152
|
increment(amount?: number, text?: string): void;
|
|
169
153
|
complete(text?: string): void;
|
|
170
154
|
private render;
|
|
155
|
+
private renderMultiLine;
|
|
156
|
+
private renderSingleLine;
|
|
171
157
|
private renderGradientBar;
|
|
172
158
|
private renderFancyBar;
|
|
173
159
|
private renderMinimalBar;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/ProgressBar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/ProgressBar.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,24 +5,18 @@
|
|
|
5
5
|
* with multiple styles and themes.
|
|
6
6
|
*/
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
-
import ora from 'ora';
|
|
9
8
|
export class ProgressBar {
|
|
10
|
-
options;
|
|
11
|
-
spinner = null;
|
|
12
9
|
percentageBar = null;
|
|
13
10
|
current = 0;
|
|
14
11
|
total = 0;
|
|
15
12
|
text = '';
|
|
16
13
|
startTime = 0;
|
|
17
14
|
style;
|
|
18
|
-
showPercentage;
|
|
19
15
|
showSpeed;
|
|
20
16
|
constructor(options = {}) {
|
|
21
|
-
this.options = options;
|
|
22
17
|
this.text = options.text || 'Processing...';
|
|
23
18
|
this.total = options.total || 0;
|
|
24
19
|
this.style = options.style || 'default';
|
|
25
|
-
this.showPercentage = options.showPercentage ?? true;
|
|
26
20
|
this.showSpeed = options.showSpeed ?? true;
|
|
27
21
|
}
|
|
28
22
|
/**
|
|
@@ -31,101 +25,17 @@ export class ProgressBar {
|
|
|
31
25
|
start(text) {
|
|
32
26
|
this.text = text || this.text;
|
|
33
27
|
this.startTime = Date.now();
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.spinner = ora({
|
|
46
|
-
text: this.getStyledText(),
|
|
47
|
-
color: this.options.color || spinnerConfig.color,
|
|
48
|
-
spinner: this.options.spinner || spinnerConfig.spinner,
|
|
49
|
-
}).start();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Get spinner configuration based on style
|
|
54
|
-
*/
|
|
55
|
-
getSpinnerConfig() {
|
|
56
|
-
switch (this.style) {
|
|
57
|
-
case 'gradient':
|
|
58
|
-
return { spinner: 'arc', color: 'magenta' };
|
|
59
|
-
case 'fancy':
|
|
60
|
-
return { spinner: 'bouncingBar', color: 'cyan' };
|
|
61
|
-
case 'minimal':
|
|
62
|
-
return { spinner: 'line', color: 'white' };
|
|
63
|
-
case 'rainbow':
|
|
64
|
-
return { spinner: 'rainbow', color: 'rainbow' };
|
|
65
|
-
case 'neon':
|
|
66
|
-
return { spinner: 'weather', color: 'green' };
|
|
67
|
-
default:
|
|
68
|
-
return { spinner: 'dots12', color: 'cyan' };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Get styled text with decorations
|
|
73
|
-
*/
|
|
74
|
-
getStyledText() {
|
|
75
|
-
const percentage = this.total > 0 ? Math.round((this.current / this.total) * 100) : 0;
|
|
76
|
-
const elapsed = Date.now() - this.startTime;
|
|
77
|
-
const speed = elapsed > 0 ? Math.round((this.current / elapsed) * 1000) : 0;
|
|
78
|
-
let styledText = this.text;
|
|
79
|
-
// Add progress information
|
|
80
|
-
if (this.total > 0) {
|
|
81
|
-
if (this.showPercentage) {
|
|
82
|
-
styledText += ` ${this.getStyledPercentage(percentage)}`;
|
|
83
|
-
}
|
|
84
|
-
styledText += ` ${this.getStyledProgress()}`;
|
|
85
|
-
if (this.showSpeed && speed > 0) {
|
|
86
|
-
styledText += ` ${chalk.gray(`(${speed}/s)`)}`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return this.applyTextStyle(styledText);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Get styled percentage based on progress
|
|
93
|
-
*/
|
|
94
|
-
getStyledPercentage(percentage) {
|
|
95
|
-
if (percentage < 25)
|
|
96
|
-
return chalk.red(`${percentage}%`);
|
|
97
|
-
if (percentage < 50)
|
|
98
|
-
return chalk.yellow(`${percentage}%`);
|
|
99
|
-
if (percentage < 75)
|
|
100
|
-
return chalk.blue(`${percentage}%`);
|
|
101
|
-
if (percentage < 100)
|
|
102
|
-
return chalk.cyan(`${percentage}%`);
|
|
103
|
-
return chalk.green(`${percentage}%`);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Get styled progress counter
|
|
107
|
-
*/
|
|
108
|
-
getStyledProgress() {
|
|
109
|
-
return chalk.gray(`(${this.current}/${this.total})`);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Apply text styling based on theme
|
|
113
|
-
*/
|
|
114
|
-
applyTextStyle(text) {
|
|
115
|
-
switch (this.style) {
|
|
116
|
-
case 'gradient':
|
|
117
|
-
return `${chalk.magenta('▶')} ${text}`;
|
|
118
|
-
case 'fancy':
|
|
119
|
-
return `${chalk.cyan('★')} ${text} ${chalk.cyan('★')}`;
|
|
120
|
-
case 'minimal':
|
|
121
|
-
return text;
|
|
122
|
-
case 'rainbow':
|
|
123
|
-
return `${chalk.magenta('◉')} ${text}`;
|
|
124
|
-
case 'neon':
|
|
125
|
-
return `${chalk.green.bold('⚡')} ${chalk.green(text)}`;
|
|
126
|
-
default:
|
|
127
|
-
return `${chalk.cyan('●')} ${text}`;
|
|
128
|
-
}
|
|
28
|
+
// 在开始新进度条前,彻底清理可能的残留内容
|
|
29
|
+
this.clearPreviousOutput();
|
|
30
|
+
// 强制使用percentageBar,即使没有total也要创建
|
|
31
|
+
// 这样可以避免spinner导致的冲突问题
|
|
32
|
+
const effectiveTotal = this.total > 0 ? this.total : 1; // 如果没有total,设为1避免除零错误
|
|
33
|
+
this.percentageBar = new PercentageProgressBar(40, {
|
|
34
|
+
style: this.style,
|
|
35
|
+
showStats: this.showSpeed,
|
|
36
|
+
multiLine: true, // 使用多行模式减少闪烁
|
|
37
|
+
});
|
|
38
|
+
this.percentageBar.start(effectiveTotal, this.text);
|
|
129
39
|
}
|
|
130
40
|
/**
|
|
131
41
|
* Update progress with text
|
|
@@ -136,14 +46,10 @@ export class ProgressBar {
|
|
|
136
46
|
this.current = current;
|
|
137
47
|
if (total !== undefined)
|
|
138
48
|
this.total = total;
|
|
49
|
+
// 只使用percentageBar,不使用spinner
|
|
139
50
|
if (this.percentageBar) {
|
|
140
|
-
// Update percentage progress bar
|
|
141
51
|
this.percentageBar.update(this.current, text);
|
|
142
52
|
}
|
|
143
|
-
else if (this.spinner) {
|
|
144
|
-
// Update spinner
|
|
145
|
-
this.spinner.text = this.getStyledText();
|
|
146
|
-
}
|
|
147
53
|
}
|
|
148
54
|
/**
|
|
149
55
|
* Increment progress
|
|
@@ -152,43 +58,33 @@ export class ProgressBar {
|
|
|
152
58
|
this.current += amount;
|
|
153
59
|
if (text)
|
|
154
60
|
this.text = text;
|
|
61
|
+
// 只使用percentageBar,不使用spinner
|
|
155
62
|
if (this.percentageBar) {
|
|
156
63
|
this.percentageBar.update(this.current, text);
|
|
157
64
|
}
|
|
158
|
-
else if (this.spinner) {
|
|
159
|
-
this.spinner.text = this.getStyledText();
|
|
160
|
-
}
|
|
161
65
|
}
|
|
162
66
|
/**
|
|
163
67
|
* Mark as succeeded
|
|
164
68
|
*/
|
|
165
69
|
succeed(text) {
|
|
70
|
+
// 只使用percentageBar,不使用spinner
|
|
166
71
|
if (this.percentageBar) {
|
|
167
72
|
const successText = text || this.getCompletionText();
|
|
168
73
|
this.percentageBar.complete(successText);
|
|
169
74
|
console.log(this.getSuccessMessage(successText));
|
|
170
75
|
this.percentageBar = null;
|
|
171
76
|
}
|
|
172
|
-
else if (this.spinner) {
|
|
173
|
-
const successText = text || this.getCompletionText();
|
|
174
|
-
this.spinner.succeed(this.getSuccessMessage(successText));
|
|
175
|
-
this.spinner = null;
|
|
176
|
-
}
|
|
177
77
|
}
|
|
178
78
|
/**
|
|
179
79
|
* Mark as failed
|
|
180
80
|
*/
|
|
181
81
|
fail(text) {
|
|
82
|
+
// 只使用percentageBar,不使用spinner
|
|
182
83
|
if (this.percentageBar) {
|
|
183
84
|
const failText = text || this.getFailureText();
|
|
184
85
|
console.log(this.getFailureMessage(failText));
|
|
185
86
|
this.percentageBar = null;
|
|
186
87
|
}
|
|
187
|
-
else if (this.spinner) {
|
|
188
|
-
const failText = text || this.getFailureText();
|
|
189
|
-
this.spinner.fail(this.getFailureMessage(failText));
|
|
190
|
-
this.spinner = null;
|
|
191
|
-
}
|
|
192
88
|
}
|
|
193
89
|
/**
|
|
194
90
|
* Get styled success message
|
|
@@ -269,31 +165,23 @@ export class ProgressBar {
|
|
|
269
165
|
* Mark as warning
|
|
270
166
|
*/
|
|
271
167
|
warn(text) {
|
|
168
|
+
// 只使用percentageBar,不使用spinner
|
|
272
169
|
if (this.percentageBar) {
|
|
273
170
|
const warnText = text || this.text;
|
|
274
171
|
console.log(this.getWarningMessage(warnText));
|
|
275
172
|
this.percentageBar = null;
|
|
276
173
|
}
|
|
277
|
-
else if (this.spinner) {
|
|
278
|
-
const warnText = text || this.text;
|
|
279
|
-
this.spinner.warn(this.getWarningMessage(warnText));
|
|
280
|
-
this.spinner = null;
|
|
281
|
-
}
|
|
282
174
|
}
|
|
283
175
|
/**
|
|
284
176
|
* Mark as info
|
|
285
177
|
*/
|
|
286
178
|
info(text) {
|
|
179
|
+
// 只使用percentageBar,不使用spinner
|
|
287
180
|
if (this.percentageBar) {
|
|
288
181
|
const infoText = text || this.text;
|
|
289
182
|
console.log(this.getInfoMessage(infoText));
|
|
290
183
|
this.percentageBar = null;
|
|
291
184
|
}
|
|
292
|
-
else if (this.spinner) {
|
|
293
|
-
const infoText = text || this.text;
|
|
294
|
-
this.spinner.info(this.getInfoMessage(infoText));
|
|
295
|
-
this.spinner = null;
|
|
296
|
-
}
|
|
297
185
|
}
|
|
298
186
|
/**
|
|
299
187
|
* Get styled warning message
|
|
@@ -339,14 +227,21 @@ export class ProgressBar {
|
|
|
339
227
|
* Stop the progress bar
|
|
340
228
|
*/
|
|
341
229
|
stop() {
|
|
230
|
+
// 只使用percentageBar,不使用spinner
|
|
342
231
|
if (this.percentageBar) {
|
|
343
|
-
// For percentage bar, just clear the instance
|
|
344
232
|
this.percentageBar = null;
|
|
345
233
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Clear previous output to prevent residual progress bars
|
|
237
|
+
*/
|
|
238
|
+
clearPreviousOutput() {
|
|
239
|
+
// 清理可能的残留进度条显示(最多清理5行,应该足够了)
|
|
240
|
+
for (let i = 0; i < 5; i++) {
|
|
241
|
+
process.stdout.write('\x1b[1A\r\x1b[K'); // 上移一行并清除
|
|
349
242
|
}
|
|
243
|
+
// 确保光标在正确位置
|
|
244
|
+
process.stdout.write('\r');
|
|
350
245
|
}
|
|
351
246
|
/**
|
|
352
247
|
* Create a multi-step progress indicator
|
|
@@ -360,8 +255,6 @@ export class ProgressBar {
|
|
|
360
255
|
static createGradient(options) {
|
|
361
256
|
return new ProgressBar({
|
|
362
257
|
style: 'gradient',
|
|
363
|
-
color: 'magenta',
|
|
364
|
-
showPercentage: true,
|
|
365
258
|
showSpeed: true,
|
|
366
259
|
...options,
|
|
367
260
|
});
|
|
@@ -372,8 +265,6 @@ export class ProgressBar {
|
|
|
372
265
|
static createFancy(options) {
|
|
373
266
|
return new ProgressBar({
|
|
374
267
|
style: 'fancy',
|
|
375
|
-
color: 'cyan',
|
|
376
|
-
showPercentage: true,
|
|
377
268
|
showSpeed: true,
|
|
378
269
|
...options,
|
|
379
270
|
});
|
|
@@ -384,8 +275,6 @@ export class ProgressBar {
|
|
|
384
275
|
static createMinimal(options) {
|
|
385
276
|
return new ProgressBar({
|
|
386
277
|
style: 'minimal',
|
|
387
|
-
color: 'white',
|
|
388
|
-
showPercentage: false,
|
|
389
278
|
showSpeed: false,
|
|
390
279
|
...options,
|
|
391
280
|
});
|
|
@@ -396,7 +285,6 @@ export class ProgressBar {
|
|
|
396
285
|
static createRainbow(options) {
|
|
397
286
|
return new ProgressBar({
|
|
398
287
|
style: 'rainbow',
|
|
399
|
-
showPercentage: true,
|
|
400
288
|
showSpeed: true,
|
|
401
289
|
...options,
|
|
402
290
|
});
|
|
@@ -407,8 +295,6 @@ export class ProgressBar {
|
|
|
407
295
|
static createNeon(options) {
|
|
408
296
|
return new ProgressBar({
|
|
409
297
|
style: 'neon',
|
|
410
|
-
color: 'green',
|
|
411
|
-
showPercentage: true,
|
|
412
298
|
showSpeed: true,
|
|
413
299
|
...options,
|
|
414
300
|
});
|
|
@@ -461,18 +347,35 @@ export class PercentageProgressBar {
|
|
|
461
347
|
lastRender = '';
|
|
462
348
|
startTime = 0;
|
|
463
349
|
style;
|
|
350
|
+
useMultiLine = true;
|
|
351
|
+
isFirstRender = true;
|
|
464
352
|
constructor(width = 40, options = {}) {
|
|
465
353
|
this.width = width;
|
|
466
354
|
this.options = options;
|
|
467
355
|
this.style = options.style || 'gradient';
|
|
356
|
+
this.useMultiLine = options.multiLine ?? true; // 默认使用多行模式来减少闪烁
|
|
468
357
|
}
|
|
469
358
|
start(total, text) {
|
|
470
359
|
this.total = total;
|
|
471
360
|
this.current = 0;
|
|
472
361
|
this.text = text;
|
|
473
362
|
this.startTime = Date.now();
|
|
363
|
+
this.isFirstRender = true; // 重置首次渲染标记
|
|
364
|
+
// 清理可能的残留输出
|
|
365
|
+
this.clearPreviousLines();
|
|
474
366
|
this.render();
|
|
475
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* Clear any previous output lines to prevent conflicts
|
|
370
|
+
*/
|
|
371
|
+
clearPreviousLines() {
|
|
372
|
+
// 更强力的清理:清理多行可能的残留内容
|
|
373
|
+
for (let i = 0; i < 6; i++) {
|
|
374
|
+
process.stdout.write('\x1b[1A\r\x1b[2K'); // 上移一行并完全清除该行
|
|
375
|
+
}
|
|
376
|
+
// 回到起始位置
|
|
377
|
+
process.stdout.write('\r');
|
|
378
|
+
}
|
|
476
379
|
update(current, text) {
|
|
477
380
|
this.current = current;
|
|
478
381
|
if (text)
|
|
@@ -496,6 +399,16 @@ export class PercentageProgressBar {
|
|
|
496
399
|
const percentage = Math.round((this.current / this.total) * 100);
|
|
497
400
|
const filledWidth = Math.round((this.current / this.total) * this.width);
|
|
498
401
|
const emptyWidth = this.width - filledWidth;
|
|
402
|
+
if (this.useMultiLine) {
|
|
403
|
+
this.renderMultiLine(percentage, filledWidth, emptyWidth);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
this.renderSingleLine(percentage, filledWidth, emptyWidth);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
renderMultiLine(percentage, filledWidth, emptyWidth) {
|
|
410
|
+
const currentText = `${this.getStyledPrefix()} ${this.text}`;
|
|
411
|
+
// 构建进度条
|
|
499
412
|
let bar;
|
|
500
413
|
switch (this.style) {
|
|
501
414
|
case 'gradient':
|
|
@@ -513,7 +426,52 @@ export class PercentageProgressBar {
|
|
|
513
426
|
default:
|
|
514
427
|
bar = this.renderDefaultBar(filledWidth, emptyWidth);
|
|
515
428
|
}
|
|
516
|
-
let
|
|
429
|
+
let progressLine = `(${this.current}/${this.total}) [${bar}] ${this.getStyledPercentage(percentage)}`;
|
|
430
|
+
// Add stats if enabled
|
|
431
|
+
if (this.options.showStats && this.startTime > 0) {
|
|
432
|
+
const elapsed = Date.now() - this.startTime;
|
|
433
|
+
const speed = elapsed > 0 ? Math.round((this.current / elapsed) * 1000) : 0;
|
|
434
|
+
if (speed > 0) {
|
|
435
|
+
progressLine += ` ${chalk.gray(`${speed}/s`)}`;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
if (this.isFirstRender) {
|
|
439
|
+
// 第一次渲染:输出两行
|
|
440
|
+
console.log(currentText);
|
|
441
|
+
console.log(progressLine);
|
|
442
|
+
this.isFirstRender = false;
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// 后续更新:回到两行前的位置,分别更新这两行
|
|
446
|
+
// 光标上移两行,清除文字行,输出新文字行
|
|
447
|
+
process.stdout.write('\x1b[2A\r\x1b[2K' + currentText + '\n');
|
|
448
|
+
// 清除进度条行,输出新进度条行
|
|
449
|
+
process.stdout.write('\r\x1b[2K' + progressLine);
|
|
450
|
+
}
|
|
451
|
+
this.lastRender = progressLine;
|
|
452
|
+
if (this.current >= this.total) {
|
|
453
|
+
process.stdout.write('\n');
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
renderSingleLine(percentage, filledWidth, emptyWidth) {
|
|
457
|
+
let bar;
|
|
458
|
+
switch (this.style) {
|
|
459
|
+
case 'gradient':
|
|
460
|
+
bar = this.renderGradientBar(filledWidth, emptyWidth);
|
|
461
|
+
break;
|
|
462
|
+
case 'fancy':
|
|
463
|
+
bar = this.renderFancyBar(filledWidth, emptyWidth);
|
|
464
|
+
break;
|
|
465
|
+
case 'minimal':
|
|
466
|
+
bar = this.renderMinimalBar(filledWidth, emptyWidth);
|
|
467
|
+
break;
|
|
468
|
+
case 'blocks':
|
|
469
|
+
bar = this.renderBlockBar(filledWidth, emptyWidth);
|
|
470
|
+
break;
|
|
471
|
+
default:
|
|
472
|
+
bar = this.renderDefaultBar(filledWidth, emptyWidth);
|
|
473
|
+
}
|
|
474
|
+
let progressText = `${this.getStyledPrefix()} ${this.text} (${this.current}/${this.total}) [${bar}] ${this.getStyledPercentage(percentage)}`;
|
|
517
475
|
// Add stats if enabled
|
|
518
476
|
if (this.options.showStats && this.startTime > 0) {
|
|
519
477
|
const elapsed = Date.now() - this.startTime;
|
|
@@ -594,25 +552,33 @@ export class PercentageProgressBar {
|
|
|
594
552
|
* Create a gradient percentage progress bar
|
|
595
553
|
*/
|
|
596
554
|
static createGradient(width = 40) {
|
|
597
|
-
return new PercentageProgressBar(width, {
|
|
555
|
+
return new PercentageProgressBar(width, {
|
|
556
|
+
style: 'gradient',
|
|
557
|
+
showStats: true,
|
|
558
|
+
multiLine: true,
|
|
559
|
+
});
|
|
598
560
|
}
|
|
599
561
|
/**
|
|
600
562
|
* Create a fancy percentage progress bar
|
|
601
563
|
*/
|
|
602
564
|
static createFancy(width = 40) {
|
|
603
|
-
return new PercentageProgressBar(width, { style: 'fancy', showStats: true });
|
|
565
|
+
return new PercentageProgressBar(width, { style: 'fancy', showStats: true, multiLine: true });
|
|
604
566
|
}
|
|
605
567
|
/**
|
|
606
568
|
* Create a minimal percentage progress bar
|
|
607
569
|
*/
|
|
608
570
|
static createMinimal(width = 40) {
|
|
609
|
-
return new PercentageProgressBar(width, {
|
|
571
|
+
return new PercentageProgressBar(width, {
|
|
572
|
+
style: 'minimal',
|
|
573
|
+
showStats: false,
|
|
574
|
+
multiLine: true,
|
|
575
|
+
});
|
|
610
576
|
}
|
|
611
577
|
/**
|
|
612
578
|
* Create a block-style percentage progress bar
|
|
613
579
|
*/
|
|
614
580
|
static createBlocks(width = 40) {
|
|
615
|
-
return new PercentageProgressBar(width, { style: 'blocks', showStats: true });
|
|
581
|
+
return new PercentageProgressBar(width, { style: 'blocks', showStats: true, multiLine: true });
|
|
616
582
|
}
|
|
617
583
|
}
|
|
618
584
|
/**
|