ygc-dsh-sync 1.2.0 → 1.2.2
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/client.js +69 -17
- package/index.js +43 -16
- package/lib/api.js +1818 -1781
- package/lib/core.js +484 -484
- package/lib/features.js +169 -154
- package/package.json +62 -62
package/client.js
CHANGED
|
@@ -295,28 +295,34 @@ function makePanel(React) {
|
|
|
295
295
|
};
|
|
296
296
|
|
|
297
297
|
/**
|
|
298
|
-
*
|
|
298
|
+
* 删工作区(= 删本机特征文件夹,1.2.1 起两者是同一件事)。
|
|
299
299
|
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
300
|
+
* 插件里不再提供「只删格子、留着工作区」的入口:那条路会让工作区变成
|
|
301
|
+
* 「已注册但没格子」,下一轮巡检必然把它列回人工队列,用户看到的就是
|
|
302
|
+
* 「删了又自己冒出来」。所以这里只保留一个动作,且必须删注册。
|
|
302
303
|
*/
|
|
303
|
-
const doDrop = async (paths
|
|
304
|
+
const doDrop = async (paths) => {
|
|
304
305
|
const list = (paths || []).filter(Boolean);
|
|
305
306
|
if (!list.length) return;
|
|
306
|
-
if (
|
|
307
|
-
if (
|
|
307
|
+
if (typeof window !== 'undefined' && typeof window.confirm === 'function') {
|
|
308
|
+
if (
|
|
309
|
+
!window.confirm(
|
|
310
|
+
'会从侧边栏删除这个工作区,并清掉本机特征文件夹(本机不再同步它)。\n目录内容、会话文件、其他机器的备份都不受影响。继续?',
|
|
311
|
+
)
|
|
312
|
+
) {
|
|
308
313
|
return;
|
|
309
314
|
}
|
|
310
315
|
}
|
|
311
316
|
setBusy('drop');
|
|
312
317
|
setNote(null);
|
|
313
318
|
try {
|
|
314
|
-
const r = await call('/features/drop', { paths: list
|
|
319
|
+
const r = await call('/features/drop', { paths: list });
|
|
320
|
+
const errs = (r.errors || []).length;
|
|
315
321
|
setNote({
|
|
316
|
-
tone:
|
|
317
|
-
text:
|
|
318
|
-
|
|
319
|
-
}
|
|
322
|
+
tone: errs ? 'warn' : 'ok',
|
|
323
|
+
text: `已删除 ${r.dropped.length} 个工作区,并清掉对应本机特征文件夹${
|
|
324
|
+
errs ? `;${errs} 个失败:${r.errors[0].message}` : ''
|
|
325
|
+
}`,
|
|
320
326
|
});
|
|
321
327
|
await load();
|
|
322
328
|
} catch (e) {
|
|
@@ -755,9 +761,11 @@ function makePanel(React) {
|
|
|
755
761
|
? (() => {
|
|
756
762
|
const pendingList = (scan && scan.pending) || (state.features && state.features.pending) || [];
|
|
757
763
|
const whyText = {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
764
|
+
// 矩阵里唯一要人决定的两档
|
|
765
|
+
othersOnly: '别的机器有特征文件夹,本机没有',
|
|
766
|
+
structureOnly: '目录里有同步结构,本机没建特征文件夹',
|
|
767
|
+
unregistered: '检测到匹配目录,本机没建特征文件夹',
|
|
768
|
+
existing: '已注册成工作区,本机没建特征文件夹',
|
|
761
769
|
declined: '你之前选了不建(可改主意)',
|
|
762
770
|
};
|
|
763
771
|
return h(
|
|
@@ -795,6 +803,9 @@ function makePanel(React) {
|
|
|
795
803
|
h('span', { className: 'dsb-tag dsb-tag-warn' }, whyText[d.why] || d.why),
|
|
796
804
|
),
|
|
797
805
|
h('div', { className: 'dsb-row-d' }, d.path),
|
|
806
|
+
d.others && d.others.length
|
|
807
|
+
? h('div', { className: 'dsb-row-d' }, `别的机器:${d.others.join(' · ')}`)
|
|
808
|
+
: null,
|
|
798
809
|
),
|
|
799
810
|
),
|
|
800
811
|
),
|
|
@@ -1007,10 +1018,10 @@ function makePanel(React) {
|
|
|
1007
1018
|
{
|
|
1008
1019
|
className: 'dsb-btn dsb-btn-sm dsb-btn-danger',
|
|
1009
1020
|
disabled: !!busy,
|
|
1010
|
-
title: '
|
|
1011
|
-
onClick: () => doDrop([w.path]
|
|
1021
|
+
title: '删除工作区,连带清掉本机特征文件夹;目录内容与别人的备份不动',
|
|
1022
|
+
onClick: () => doDrop([w.path]),
|
|
1012
1023
|
},
|
|
1013
|
-
'
|
|
1024
|
+
'删除工作区',
|
|
1014
1025
|
),
|
|
1015
1026
|
),
|
|
1016
1027
|
),
|
|
@@ -1051,6 +1062,47 @@ function makePanel(React) {
|
|
|
1051
1062
|
),
|
|
1052
1063
|
)
|
|
1053
1064
|
: null,
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* 你点过「跳过」的目录。
|
|
1068
|
+
*
|
|
1069
|
+
* 跳过的语义就是「从待决定清单里消失」,所以它必须在这里有个落点,
|
|
1070
|
+
* 否则改不了主意只能翻文件。点「改为建特征文件夹」走 /features/adopt,
|
|
1071
|
+
* 会顺手把跳过记录清掉。
|
|
1072
|
+
*/
|
|
1073
|
+
(state.features && (state.features.declined || []).length)
|
|
1074
|
+
? h(
|
|
1075
|
+
'div',
|
|
1076
|
+
{ style: { marginTop: 14 } },
|
|
1077
|
+
h(
|
|
1078
|
+
'div',
|
|
1079
|
+
{ className: 'dsb-row-t', style: { marginBottom: 6 } },
|
|
1080
|
+
`已跳过:${state.features.declined.length} 个(不再询问,可改主意)`,
|
|
1081
|
+
),
|
|
1082
|
+
(state.features.declined || []).map((w) =>
|
|
1083
|
+
h(
|
|
1084
|
+
'div',
|
|
1085
|
+
{ className: 'dsb-row', key: w.path },
|
|
1086
|
+
h(
|
|
1087
|
+
'div',
|
|
1088
|
+
{ className: 'dsb-row-main' },
|
|
1089
|
+
h('div', { className: 'dsb-row-t' }, w.title),
|
|
1090
|
+
h('div', { className: 'dsb-row-d' }, '你选了不在这个目录建本机特征文件夹'),
|
|
1091
|
+
h('div', { className: 'dsb-row-d' }, w.path),
|
|
1092
|
+
),
|
|
1093
|
+
h(
|
|
1094
|
+
'button',
|
|
1095
|
+
{
|
|
1096
|
+
className: 'dsb-btn dsb-btn-sm',
|
|
1097
|
+
disabled: !!busy,
|
|
1098
|
+
onClick: () => doAdopt([w.path]),
|
|
1099
|
+
},
|
|
1100
|
+
'改为建特征文件夹',
|
|
1101
|
+
),
|
|
1102
|
+
),
|
|
1103
|
+
),
|
|
1104
|
+
)
|
|
1105
|
+
: null,
|
|
1054
1106
|
),
|
|
1055
1107
|
|
|
1056
1108
|
// 插件清单同步(1.0.0 从自动更新器迁入)
|
package/index.js
CHANGED
|
@@ -295,13 +295,13 @@ export function apply(ctx, config = {}) {
|
|
|
295
295
|
});
|
|
296
296
|
|
|
297
297
|
// ---- 定时巡检 ----
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
//
|
|
298
|
+
// 判据(用户 2026-11-14 定的矩阵,只认磁盘上有没有那三个东西):
|
|
299
|
+
// 别人的格子 有 / 我的格子 没有 / 工作区 没有 → 问人要不要在本机建
|
|
300
|
+
// 我的格子 有 / 工作区 有 → 正常,参与备份与拉取
|
|
301
|
+
// 我的格子 有 / 工作区 没有 → 补工作区(注册回侧边栏)
|
|
302
|
+
// 我的格子 没有 / 工作区 有 → 补文件夹
|
|
303
|
+
// 工作区被删(基线里有、清单里没有) → 删我的格子(含格里对话)
|
|
304
|
+
// 补工作区这一步要调宿主接口(async),所以放在这里做,不在纯函数里。
|
|
305
305
|
const runPatrol = async (reason) => {
|
|
306
306
|
try {
|
|
307
307
|
const state = loadState();
|
|
@@ -313,7 +313,6 @@ export function apply(ctx, config = {}) {
|
|
|
313
313
|
machineId: mid,
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
-
// 特征文件夹计划:adopt / restore / drop 自动做,pending 留给人
|
|
317
316
|
const plan = planFeatures({
|
|
318
317
|
folders: state.folders,
|
|
319
318
|
workspaces: all,
|
|
@@ -322,9 +321,31 @@ export function apply(ctx, config = {}) {
|
|
|
322
321
|
machineId: mid,
|
|
323
322
|
});
|
|
324
323
|
const next = loadState();
|
|
324
|
+
// 补文件夹 + 删格子(这两件是同步的、不涉及注册)
|
|
325
325
|
const applied = applyFeaturePlan({ plan, state: next, machineId: mid, log });
|
|
326
326
|
saveState(next);
|
|
327
327
|
|
|
328
|
+
// 补工作区:有我的格子、但侧边栏里没有它
|
|
329
|
+
const restoredWs = [];
|
|
330
|
+
const restoreErrors = [];
|
|
331
|
+
if (typeof registerWorkspace === 'function') {
|
|
332
|
+
for (const item of plan.restoreWorkspace || []) {
|
|
333
|
+
try {
|
|
334
|
+
const out = await registerWorkspace(item.path, item.title);
|
|
335
|
+
restoredWs.push({ path: item.path, id: out?.id });
|
|
336
|
+
} catch (err) {
|
|
337
|
+
restoreErrors.push({ path: item.path, message: String((err && err.message) || err) });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (restoredWs.length) {
|
|
341
|
+
const s2 = loadState();
|
|
342
|
+
for (const r of restoredWs) {
|
|
343
|
+
if (r.id !== undefined && r.id !== null) s2.features.known[String(r.id)] = String(r.path).replace(/[\\/]+/g, '\\');
|
|
344
|
+
}
|
|
345
|
+
saveState(s2);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
328
349
|
const attachment = await repairAttachments();
|
|
329
350
|
|
|
330
351
|
const after = loadState();
|
|
@@ -334,9 +355,9 @@ export function apply(ctx, config = {}) {
|
|
|
334
355
|
lastResult: {
|
|
335
356
|
discover: scan.discover.length,
|
|
336
357
|
repair: scan.repair.length,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
358
|
+
ask: plan.ask.length,
|
|
359
|
+
createdFolder: applied.created.length,
|
|
360
|
+
restoredWorkspace: restoredWs.length,
|
|
340
361
|
dropped: applied.dropped.length,
|
|
341
362
|
attached: attachment.attached,
|
|
342
363
|
attachFailed: attachment.failed,
|
|
@@ -346,16 +367,22 @@ export function apply(ctx, config = {}) {
|
|
|
346
367
|
pushHistory(
|
|
347
368
|
after,
|
|
348
369
|
'patrol',
|
|
349
|
-
`巡检(${reason}):待人工确认 ${plan.
|
|
350
|
-
|
|
370
|
+
`巡检(${reason}):待人工确认 ${plan.ask.length} 个、补文件夹 ${applied.created.length} 个、` +
|
|
371
|
+
`补工作区 ${restoredWs.length} 个、删格子 ${applied.dropped.length} 个` +
|
|
351
372
|
`${attachment.attached ? `、补登记 ${attachment.attached} 个会话归属` : ''}`,
|
|
352
373
|
);
|
|
353
374
|
saveState(after);
|
|
354
375
|
|
|
355
|
-
if (
|
|
376
|
+
if (
|
|
377
|
+
plan.ask.length ||
|
|
378
|
+
applied.created.length ||
|
|
379
|
+
restoredWs.length ||
|
|
380
|
+
applied.dropped.length ||
|
|
381
|
+
attachment.attached
|
|
382
|
+
) {
|
|
356
383
|
log(
|
|
357
|
-
`巡检:待人工确认 ${plan.
|
|
358
|
-
|
|
384
|
+
`巡检:待人工确认 ${plan.ask.length},补文件夹 ${applied.created.length},补工作区 ${restoredWs.length},` +
|
|
385
|
+
`删格子 ${applied.dropped.length},补登记 ${attachment.attached}`,
|
|
359
386
|
);
|
|
360
387
|
}
|
|
361
388
|
return after.patrol;
|