@cloud411716/fancy-webnovel 1.0.13 → 1.0.15
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/commands/scan/index.js +43 -5
- package/package.json +1 -1
package/commands/scan/index.js
CHANGED
|
@@ -16,6 +16,42 @@ import * as qimao from './platforms/qimao.js';
|
|
|
16
16
|
|
|
17
17
|
// inject is declared in the root index.js; only apply() is imported by index.js
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* StatusLine — appends a single session event and updates it in-place on
|
|
21
|
+
* subsequent calls using session's surfaceOp replace mechanism.
|
|
22
|
+
*
|
|
23
|
+
* The event always stays at the same log position; only its content changes.
|
|
24
|
+
* This gives the appearance of a terminal "status bar" that doesn't scroll
|
|
25
|
+
* away or get buried under other messages.
|
|
26
|
+
*/
|
|
27
|
+
class StatusLine {
|
|
28
|
+
#session;
|
|
29
|
+
#seq; // event sequence of the status line (set after first append)
|
|
30
|
+
#text = '';
|
|
31
|
+
|
|
32
|
+
constructor(session) { this.#session = session; }
|
|
33
|
+
|
|
34
|
+
/** Update the status line content. First call creates the event; subsequent
|
|
35
|
+
* calls replace it in-place. */
|
|
36
|
+
update(text) {
|
|
37
|
+
const event = this.#seq
|
|
38
|
+
? this.#session.append(
|
|
39
|
+
'fancy/status',
|
|
40
|
+
{ content: [{ type: 'text', text }], source: { kind: 'user' } },
|
|
41
|
+
{ surfaceOp: { op: 'replace', start: this.#seq, end: this.#seq } }
|
|
42
|
+
)
|
|
43
|
+
: this.#session.append(
|
|
44
|
+
'fancy/status',
|
|
45
|
+
{ content: [{ type: 'text', text }], source: { kind: 'user' } },
|
|
46
|
+
{ surfaceOp: 'append' }
|
|
47
|
+
);
|
|
48
|
+
this.#seq ??= event.seq;
|
|
49
|
+
this.#text = text;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
clear() { this.update(''); }
|
|
53
|
+
}
|
|
54
|
+
|
|
19
55
|
const PLATFORM_TABLE = [
|
|
20
56
|
['1', 'qidian', '起点'],
|
|
21
57
|
['2', 'fanqie', '番茄'],
|
|
@@ -196,18 +232,19 @@ export function apply(ctx) {
|
|
|
196
232
|
// ---------- in-process scraping (no subprocess) ----------
|
|
197
233
|
|
|
198
234
|
// Register scan-progress listeners before scraping starts, clean up after.
|
|
199
|
-
//
|
|
200
|
-
//
|
|
235
|
+
// StatusLine.update() uses session surfaceOp replace so the status stays
|
|
236
|
+
// at the same log position and doesn't accumulate or scroll away.
|
|
201
237
|
const disposers = [];
|
|
238
|
+
const statusLine = new StatusLine(session);
|
|
202
239
|
let currentRankLabel = '';
|
|
203
240
|
|
|
204
241
|
disposers.push(ctx.events.on('fancy/scan:start', (_ctx, platform, _channel, _type, label) => {
|
|
205
242
|
currentRankLabel = label;
|
|
206
|
-
|
|
243
|
+
statusLine.update(`[${SPINNER[_spinnerIdx++ % 4]}] 正在采集:${platformLabel(platform)} ${label} …`);
|
|
207
244
|
}));
|
|
208
245
|
|
|
209
246
|
disposers.push(ctx.events.on('fancy/scan:rank-done', (_ctx, _platform, _channel, _type, ok, written) => {
|
|
210
|
-
|
|
247
|
+
statusLine.update(`[${SPINNER[_spinnerIdx++ % 4]}] ${currentRankLabel} ${ok ? `✓ 写入 ${written} 条` : '✗ 失败'}`);
|
|
211
248
|
}));
|
|
212
249
|
|
|
213
250
|
const { totalBooks, totalFiles, failedRanks, lastReceipt } = await runScans(
|
|
@@ -217,8 +254,9 @@ export function apply(ctx) {
|
|
|
217
254
|
signal,
|
|
218
255
|
);
|
|
219
256
|
|
|
220
|
-
// Clean up progress listeners
|
|
257
|
+
// Clean up progress listeners and clear the status bar.
|
|
221
258
|
for (const d of disposers) d();
|
|
259
|
+
statusLine.clear();
|
|
222
260
|
|
|
223
261
|
// ---------- output results ----------
|
|
224
262
|
if (lastReceipt && totalFiles > 0) {
|