优化
This commit is contained in:
@ -4,7 +4,7 @@
|
|||||||
"glb2": 3
|
"glb2": 3
|
||||||
},
|
},
|
||||||
"image_operation": {
|
"image_operation": {
|
||||||
"compress": 8,
|
"compress": 9,
|
||||||
"resize": 1
|
"resize": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -15,75 +15,77 @@ const OPERATIONS = [
|
|||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
// 强制清理并重新初始化键盘
|
||||||
// 强制清理并重新初始化键盘
|
stopKeypress();
|
||||||
stopKeypress();
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
|
|
||||||
const steps = getSteps();
|
const steps = getSteps();
|
||||||
const ui = createStepUI({ title, getSteps: () => steps });
|
const ui = createStepUI({
|
||||||
const result = await ui.runInteractive();
|
title,
|
||||||
|
getSteps: () => steps,
|
||||||
if (!result) {
|
validate: (results) => {
|
||||||
stopKeypress();
|
// 验证是否有文件选择且至少有一个操作未跳过
|
||||||
return "back";
|
const files = results[0] || [];
|
||||||
|
const hasOperation = OPERATIONS.some(op => results[op.stepIndex] !== "skip");
|
||||||
|
return files.length > 0 && hasOperation;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const files = result.results[0] || [];
|
const result = await ui.runInteractive();
|
||||||
const selectedOp = OPERATIONS.find(op => result.results[op.stepIndex] !== "skip");
|
|
||||||
|
|
||||||
stopKeypress();
|
if (!result) {
|
||||||
|
|
||||||
// 如果没有选择文件或所有操作都跳过,重新开始
|
|
||||||
if (!selectedOp || !files.length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 有效的选择,继续处理
|
|
||||||
const params = buildProcessParams(selectedOp.id, result.results[selectedOp.stepIndex]);
|
|
||||||
|
|
||||||
ui.showSummary([
|
|
||||||
"源文件: " + files.join(", "),
|
|
||||||
"操作: " + selectedOp.name,
|
|
||||||
getParamLabel(selectedOp.id, params)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const total = files.length;
|
|
||||||
let success = 0;
|
|
||||||
const failed = [];
|
|
||||||
|
|
||||||
console.log(color.cyan(`开始处理 ${total} 个文件...\\n`));
|
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
const file = files[i];
|
|
||||||
const progress = `[${i + 1}/${total}]`;
|
|
||||||
console.log(color.dim(`${progress} 处理中: ${file}`));
|
|
||||||
|
|
||||||
try {
|
|
||||||
const outputs = await processImage(file, selectedOp.id, params);
|
|
||||||
success++;
|
|
||||||
record("image_operation", selectedOp.id);
|
|
||||||
|
|
||||||
const outputNames = Array.isArray(outputs)
|
|
||||||
? outputs.map(o => path.relative(process.cwd(), o)).join(", ")
|
|
||||||
: path.relative(process.cwd(), outputs);
|
|
||||||
console.log(color.green(`${progress} ✓ ${file} → ${outputNames}`));
|
|
||||||
} catch (err) {
|
|
||||||
failed.push({ file, reason: err?.message || String(err) });
|
|
||||||
console.log(color.red(`${progress} ✖ 失败: ${file}`));
|
|
||||||
console.log(color.dim(" " + String(err?.message || err)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("\\n" + color.bgGreen(color.black(" 处理完成 ")));
|
|
||||||
console.log(color.green(`成功: ${success} 个`));
|
|
||||||
if (failed.length) console.log(color.yellow(`失败: ${failed.length} 个`));
|
|
||||||
console.log(color.cyan(`输出目录: ${selectedOp.folder}/`));
|
|
||||||
|
|
||||||
await waitForKey(color.dim("按 Esc 返回"), key => key?.name === "escape" || (key?.ctrl && key?.name === "c"));
|
|
||||||
stopKeypress();
|
stopKeypress();
|
||||||
return "back";
|
return "back";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const files = result.results[0] || [];
|
||||||
|
const selectedOp = OPERATIONS.find(op => result.results[op.stepIndex] !== "skip");
|
||||||
|
|
||||||
|
stopKeypress();
|
||||||
|
|
||||||
|
const params = buildProcessParams(selectedOp.id, result.results[selectedOp.stepIndex]);
|
||||||
|
|
||||||
|
ui.showSummary([
|
||||||
|
"源文件: " + files.join(", "),
|
||||||
|
"操作: " + selectedOp.name,
|
||||||
|
getParamLabel(selectedOp.id, params)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const total = files.length;
|
||||||
|
let success = 0;
|
||||||
|
const failed = [];
|
||||||
|
|
||||||
|
console.log(color.cyan(`开始处理 ${total} 个文件...\\n`));
|
||||||
|
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
const progress = `[${i + 1}/${total}]`;
|
||||||
|
console.log(color.dim(`${progress} 处理中: ${file}`));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const outputs = await processImage(file, selectedOp.id, params);
|
||||||
|
success++;
|
||||||
|
record("image_operation", selectedOp.id);
|
||||||
|
|
||||||
|
const outputNames = Array.isArray(outputs)
|
||||||
|
? outputs.map(o => path.relative(process.cwd(), o)).join(", ")
|
||||||
|
: path.relative(process.cwd(), outputs);
|
||||||
|
console.log(color.green(`${progress} ✓ ${file} → ${outputNames}`));
|
||||||
|
} catch (err) {
|
||||||
|
failed.push({ file, reason: err?.message || String(err) });
|
||||||
|
console.log(color.red(`${progress} ✖ 失败: ${file}`));
|
||||||
|
console.log(color.dim(" " + String(err?.message || err)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\\n" + color.bgGreen(color.black(" 处理完成 ")));
|
||||||
|
console.log(color.green(`成功: ${success} 个`));
|
||||||
|
if (failed.length) console.log(color.yellow(`失败: ${failed.length} 个`));
|
||||||
|
console.log(color.cyan(`输出目录: ${selectedOp.folder}/`));
|
||||||
|
|
||||||
|
await waitForKey(color.dim("按 Esc 返回"), key => key?.name === "escape" || (key?.ctrl && key?.name === "c"));
|
||||||
|
stopKeypress();
|
||||||
|
return "back";
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
stopKeypress();
|
stopKeypress();
|
||||||
console.error(color.red("发生错误:"), err);
|
console.error(color.red("发生错误:"), err);
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { initKeypress, onKey, stopKeypress } from "../keyboard.js";
|
|||||||
import { clearScreen } from "./terminal.js";
|
import { clearScreen } from "./terminal.js";
|
||||||
|
|
||||||
export function createStepUI(options) {
|
export function createStepUI(options) {
|
||||||
const { title, getSteps, onStepChange } = options;
|
const { title, getSteps, onStepChange, validate } = options;
|
||||||
|
|
||||||
let steps = [];
|
let steps = [];
|
||||||
let results = [];
|
let results = [];
|
||||||
@ -171,6 +171,11 @@ export function createStepUI(options) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "tab":
|
case "tab":
|
||||||
|
// 如果提供了验证函数,先验证
|
||||||
|
if (validate && !validate(results)) {
|
||||||
|
// 验证失败,忽略此次提交
|
||||||
|
break;
|
||||||
|
}
|
||||||
resolved = true;
|
resolved = true;
|
||||||
stopKeypress();
|
stopKeypress();
|
||||||
setImmediate(() => resolve({ steps, results }));
|
setImmediate(() => resolve({ steps, results }));
|
||||||
|
|||||||
Reference in New Issue
Block a user