dsh-config-manager 0.1.20 → 0.1.21

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.
Files changed (54) hide show
  1. package/lib/client.d.ts +312 -46
  2. package/lib/client.js +1172 -205
  3. package/lib/client.js.map +1 -1
  4. package/lib/core/run-registry.d.ts +2 -2
  5. package/lib/core/run-registry.js +5 -1
  6. package/lib/core/run-registry.js.map +1 -1
  7. package/lib/index.js +292 -19
  8. package/lib/index.js.map +1 -1
  9. package/lib/sync/autosync-config.d.ts +34 -0
  10. package/lib/sync/autosync-config.js +116 -0
  11. package/lib/sync/autosync-config.js.map +1 -0
  12. package/lib/sync/autosync-scheduler.d.ts +95 -0
  13. package/lib/sync/autosync-scheduler.js +379 -0
  14. package/lib/sync/autosync-scheduler.js.map +1 -0
  15. package/lib/sync/sync-engine.d.ts +59 -4
  16. package/lib/sync/sync-engine.js +138 -12
  17. package/lib/sync/sync-engine.js.map +1 -1
  18. package/lib/sync/sync-history.d.ts +39 -0
  19. package/lib/sync/sync-history.js +88 -0
  20. package/lib/sync/sync-history.js.map +1 -0
  21. package/lib/sync/sync-session.d.ts +39 -0
  22. package/lib/sync/sync-session.js +54 -0
  23. package/lib/sync/sync-session.js.map +1 -0
  24. package/lib/ui/i18n.d.ts +63 -0
  25. package/lib/ui/i18n.js +130 -1
  26. package/lib/ui/i18n.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/client/config-manager.module.css +18 -0
  29. package/src/client/sync/SyncConfirmView.tsx +301 -0
  30. package/src/client/sync/SyncHistoryView.tsx +107 -25
  31. package/src/client/sync/SyncSettingsView.tsx +226 -83
  32. package/src/client/sync/history-model.test.ts +82 -0
  33. package/src/client/sync/history-model.ts +89 -2
  34. package/src/client/sync/sync-api.test.ts +155 -0
  35. package/src/client/sync/sync-api.ts +208 -16
  36. package/src/client/sync/sync-locales.ts +162 -1
  37. package/src/client/sync/sync-view-v2.test.ts +131 -0
  38. package/src/client/sync/sync-view.ts +151 -4
  39. package/src/core/run-registry.ts +7 -3
  40. package/src/index.ts +314 -22
  41. package/src/sync/autosync-config.test.ts +93 -0
  42. package/src/sync/autosync-config.ts +137 -0
  43. package/src/sync/autosync-scheduler.test.ts +191 -0
  44. package/src/sync/autosync-scheduler.ts +443 -0
  45. package/src/sync/sync-engine.test.ts +107 -7
  46. package/src/sync/sync-engine.ts +176 -14
  47. package/src/sync/sync-history.test.ts +85 -0
  48. package/src/sync/sync-history.ts +126 -0
  49. package/src/sync/sync-session.test.ts +137 -0
  50. package/src/sync/sync-session.ts +76 -0
  51. package/src/ui/i18n.ts +132 -3
  52. package/src/client/sync/SyncPullPreviewView.test.ts +0 -54
  53. package/src/client/sync/SyncPullPreviewView.tsx +0 -165
  54. package/src/client/sync/pull-preview-model.ts +0 -44
package/lib/ui/i18n.js CHANGED
@@ -157,6 +157,72 @@ export const uiZh = {
157
157
  'sync.pullOk': '远端快照 {id} 差异预览:共 {count} 项变更',
158
158
  'sync.pullEmpty': '远端快照与本地一致(无变更)',
159
159
  'sync.previewHint': '以上为只读差异预览,不会执行导入。v1 暂不提供一键导入接线;如需应用远端配置,请使用「导入恢复」向导手动导入导出的备份。',
160
+ // 一键同步(方案 A:拉取 → 逐项确认 → apply-items)
161
+ 'sync.syncTitle': '一键同步',
162
+ 'sync.syncButton': '一键同步',
163
+ 'sync.syncing': '正在同步…',
164
+ 'sync.syncHeadline': '远端快照 {id} 差异确认:共 {count} 项',
165
+ 'sync.syncEmpty': '远端快照与本地一致(无变更)',
166
+ 'sync.syncFailed': '同步失败',
167
+ 'sync.confirmAdopt': '采用远端',
168
+ 'sync.confirmSkip': '跳过',
169
+ 'sync.confirmRequired': '需要人工决策',
170
+ 'sync.needsReviewBadge': '需人工决策',
171
+ 'sync.selectSnapshot': '选择历史快照',
172
+ 'sync.latestSnapshot': '最新快照',
173
+ 'sync.noSnapshots': '远端暂无快照',
174
+ 'sync.confirmImport': '确认导入',
175
+ 'sync.cancelConfirm': '取消',
176
+ 'sync.conflictResolve': '冲突解决',
177
+ 'sync.conflictUseLocal': '用本地',
178
+ 'sync.conflictUseRemote': '用远端',
179
+ 'sync.conflictSkip': '跳过',
180
+ 'sync.conflictResolvedLocal': '已选:本地',
181
+ 'sync.conflictResolvedRemote': '已选:远端',
182
+ 'sync.conflictResolvedSkip': '已选:跳过',
183
+ 'sync.importDone': '已导入 {n} 个分区',
184
+ 'sync.importSkipped': '已跳过 {n} 项',
185
+ 'sync.importFailed': '导入失败(已整体回滚)',
186
+ 'sync.rollbackButton': '回滚到应用前',
187
+ 'sync.rollingBack': '正在回滚…',
188
+ 'sync.rollbackDone': '已回滚到应用前',
189
+ 'sync.appliedSections': '已写入',
190
+ 'sync.importWarnings': '导入告警',
191
+ // 自动同步(方案 A:宿主后台调度)
192
+ 'sync.autosyncTitle': '自动同步',
193
+ 'sync.autosyncDesc': '开启后,DSH 将按固定间隔自动执行双向同步(拉取合并 + 上传);DSH 启动时还会触发一次「自动下载合并(不上传)」以保持本地为最新。仅在无冲突且无需人工干预时才自动写入。',
194
+ 'sync.autosyncEnabled': '启用自动同步',
195
+ 'sync.autosyncInterval': '同步间隔',
196
+ 'sync.autosyncIntervalHint': 'DSH 启动时自动下载合并不上传。',
197
+ 'sync.autosyncNever': '从未运行',
198
+ 'sync.autosyncLastRun': '上次运行:{time}',
199
+ 'sync.autosyncNextIn': '下次约 {time} 后',
200
+ 'sync.autosyncSuccess': '成功',
201
+ 'sync.autosyncSkipped': '已跳过',
202
+ 'sync.autosyncFailed': '失败',
203
+ 'sync.autosyncPartial': '部分成功',
204
+ 'sync.autosyncFailCount': '连续失败 {n} 次',
205
+ 'sync.autosyncSyncing': '自动同步进行中…',
206
+ 'sync.interval.5m': '5 分钟',
207
+ 'sync.interval.15m': '15 分钟',
208
+ 'sync.interval.30m': '30 分钟',
209
+ 'sync.interval.60m': '60 分钟',
210
+ 'sync.interval.6h': '6 小时',
211
+ 'sync.interval.12h': '12 小时',
212
+ 'sync.interval.24h': '24 小时',
213
+ // 自动同步历史(kind=autosync 行渲染)
214
+ 'sync.hist.autosync': '自动同步',
215
+ 'sync.hist.directionPull': '下载',
216
+ 'sync.hist.directionPush': '上传',
217
+ 'sync.hist.directionBoth': '双向',
218
+ 'sync.hist.skipReasonConflict': '冲突项被跳过',
219
+ 'sync.hist.skipReasonNoRemote': '远端无快照',
220
+ 'sync.hist.skipReasonNotConfigured': '未配置仓库',
221
+ 'sync.hist.skipReasonNetwork': '网络问题',
222
+ 'sync.hist.conflictedSections': '跳过冲突分区:{sections}',
223
+ 'sync.hist.appliedSections': '应用分区:{sections}',
224
+ 'sync.hist.failedError': '错误:{error}',
225
+ 'sync.hist.notifiedAt': '已通知',
160
226
  // GitHub OAuth 区块
161
227
  'sync.github.starting': '正在发起 GitHub 授权…',
162
228
  'sync.github.waitingNoCode': '请在浏览器中打开授权页面并完成授权…',
@@ -314,7 +380,70 @@ export const uiEn = {
314
380
  'sync.pullOk': 'Remote snapshot {id} diff preview: {count} change(s)',
315
381
  'sync.pullEmpty': 'Remote snapshot matches local (no changes)',
316
382
  'sync.previewHint': 'Read-only diff preview above; nothing is imported. v1 does not wire one-click import yet — use the Import wizard to apply a downloaded backup if needed.',
317
- 'sync.github.starting': 'Starting GitHub authorization…',
383
+ 'sync.syncTitle': 'One-Click Sync',
384
+ 'sync.syncButton': 'One-click sync',
385
+ 'sync.syncing': 'Syncing…',
386
+ 'sync.syncHeadline': 'Remote snapshot {id} diff confirm: {count} item(s)',
387
+ 'sync.syncEmpty': 'Remote snapshot matches local (no changes)',
388
+ 'sync.syncFailed': 'Sync failed',
389
+ 'sync.confirmAdopt': 'Adopt remote',
390
+ 'sync.confirmSkip': 'Skip',
391
+ 'sync.confirmRequired': 'Needs decision',
392
+ 'sync.needsReviewBadge': 'Needs decision',
393
+ 'sync.selectSnapshot': 'Select snapshot',
394
+ 'sync.latestSnapshot': 'Latest snapshot',
395
+ 'sync.noSnapshots': 'No remote snapshots',
396
+ 'sync.confirmImport': 'Confirm import',
397
+ 'sync.cancelConfirm': 'Cancel',
398
+ 'sync.conflictResolve': 'Resolve conflict',
399
+ 'sync.conflictUseLocal': 'Use local',
400
+ 'sync.conflictUseRemote': 'Use remote',
401
+ 'sync.conflictSkip': 'Skip',
402
+ 'sync.conflictResolvedLocal': 'Chosen: local',
403
+ 'sync.conflictResolvedRemote': 'Chosen: remote',
404
+ 'sync.conflictResolvedSkip': 'Chosen: skip',
405
+ 'sync.importDone': 'Imported {n} section(s)',
406
+ 'sync.importSkipped': 'Skipped {n} item(s)',
407
+ 'sync.importFailed': 'Import failed (rolled back)',
408
+ 'sync.rollbackButton': 'Rollback',
409
+ 'sync.rollingBack': 'Rolling back…',
410
+ 'sync.rollbackDone': 'Rolled back',
411
+ 'sync.appliedSections': 'Written',
412
+ 'sync.importWarnings': 'Import warnings',
413
+ 'sync.autosyncTitle': 'Auto Sync',
414
+ 'sync.autosyncDesc': 'When enabled, DSH will run two-way sync (pull merge + push) on a fixed interval; on startup it also triggers a download-merge (no upload) to keep local up to date. Local writes happen only when there are no conflicts or manual-decision items.',
415
+ 'sync.autosyncEnabled': 'Enable auto sync',
416
+ 'sync.autosyncInterval': 'Sync interval',
417
+ 'sync.autosyncIntervalHint': 'Auto download-merge on DSH startup, no upload.',
418
+ 'sync.autosyncNever': 'Never run',
419
+ 'sync.autosyncLastRun': 'Last run: {time}',
420
+ 'sync.autosyncNextIn': 'Next in ~{time}',
421
+ 'sync.autosyncSuccess': 'Success',
422
+ 'sync.autosyncSkipped': 'Skipped',
423
+ 'sync.autosyncFailed': 'Failed',
424
+ 'sync.autosyncPartial': 'Partial',
425
+ 'sync.autosyncFailCount': '{n} consecutive failure(s)',
426
+ 'sync.autosyncSyncing': 'Auto sync running…',
427
+ 'sync.interval.5m': '5 min',
428
+ 'sync.interval.15m': '15 min',
429
+ 'sync.interval.30m': '30 min',
430
+ 'sync.interval.60m': '60 min',
431
+ 'sync.interval.6h': '6 hr',
432
+ 'sync.interval.12h': '12 hr',
433
+ 'sync.interval.24h': '24 hr',
434
+ 'sync.hist.autosync': 'Auto Sync',
435
+ 'sync.hist.directionPull': 'Pull',
436
+ 'sync.hist.directionPush': 'Push',
437
+ 'sync.hist.directionBoth': 'Both',
438
+ 'sync.hist.skipReasonConflict': 'Conflict items skipped',
439
+ 'sync.hist.skipReasonNoRemote': 'No remote snapshot',
440
+ 'sync.hist.skipReasonNotConfigured': 'No repository configured',
441
+ 'sync.hist.skipReasonNetwork': 'Network issue',
442
+ 'sync.hist.conflictedSections': 'Skipped conflict sections: {sections}',
443
+ 'sync.hist.appliedSections': 'Applied sections: {sections}',
444
+ 'sync.hist.failedError': 'Error: {error}',
445
+ 'sync.hist.notifiedAt': 'Notified',
446
+ 'sync.github.starting': 'Starting GitHub a​u​t​h​o​r​i​z​a​t​i​o​n​…',
318
447
  'sync.github.waitingNoCode': 'Open the authorization page in your browser and complete the flow…',
319
448
  'sync.github.waiting': 'Open the authorization page in your browser, enter the one-time code {code} to finish (waiting for confirmation).',
320
449
  'sync.github.polling': 'Confirming GitHub authorization…',
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/ui/i18n.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/ui/i18n.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-config-manager",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "DSH Config Manager — backup / export / import / migrate DSH configuration (dual-face Cordis plugin: host engine + web UI). Manifest shape mirrors @linxin666/dsh-ssh@0.1.12.",
5
5
  "keywords": [
6
6
  "dsh",
@@ -867,3 +867,21 @@
867
867
  gap: 8px;
868
868
  margin-top: 10px;
869
869
  }
870
+
871
+ /* 拉取差异预览(details 展开后的 diff):限高 + 内部滚动,diff 项多时不把整页撑长 */
872
+ .diffScroll {
873
+ margin: 0;
874
+ max-height: 240px;
875
+ overflow: auto;
876
+ overscroll-behavior: contain;
877
+ padding: 8px 10px;
878
+ background: var(--dsw-alias-bg-base);
879
+ border: 1px solid var(--dsw-alias-border-l2);
880
+ border-radius: 8px;
881
+ white-space: pre-wrap;
882
+ word-break: break-all;
883
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
884
+ font-size: 11.5px;
885
+ line-height: 1.6;
886
+ color: var(--dsw-alias-label-primary);
887
+ }
@@ -0,0 +1,301 @@
1
+ /**
2
+ * 一键同步差异确认视图(方案 A §5 差异确认数据流)。
3
+ *
4
+ * 消费 POST /sync/sync 返回的 items[],渲染逐项确认列表:
5
+ * - 每项:kindTag + description + severity + 「采用远端」复选框(默认勾选,可取消);
6
+ * - Conflict 项:内联弹窗(用本地 / 用远端 / 跳过);
7
+ * - 底部:「确认导入」(apply-items)+「取消」(cancel)。
8
+ *
9
+ * 全部渲染模型来自 ./sync-view.ts 纯函数(node 单测覆盖),组件只做装配 + 交互状态。
10
+ */
11
+ import { useMemo, useState } from 'react'
12
+ import type { ReactNode } from 'react'
13
+
14
+ import { Badge, Banner, Button, Card, Spinner } from '../common/ui.tsx'
15
+ import type { SyncApi, SyncConfirmItem } from './sync-api.ts'
16
+ import { kindLabel, severityLabel, summarizeConfirmItems } from './sync-view.ts'
17
+ import type { ApplyItemsResponse } from './sync-api.ts'
18
+ import type { TranslateNS } from '../client-types.ts'
19
+ import css from '../config-manager.module.css'
20
+
21
+ export interface SyncConfirmViewProps {
22
+ api: SyncApi
23
+ /** 差异确认会话 id(apply-items / cancel 引用)。 */
24
+ syncSessionId: string
25
+ /** 被拉取的远端快照 id。 */
26
+ snapshotId: string
27
+ items: SyncConfirmItem[]
28
+ needsReview: boolean
29
+ /** 兼容性评级(可选展示)。 */
30
+ compatibility?: 'excellent' | 'good' | 'partial' | 'unsupported'
31
+ /** 翻译器。 */
32
+ t: TranslateNS<'config-manager-sync'>
33
+ /** 用户取消确认后回调(复位到空闲态)。 */
34
+ onCancel: () => void
35
+ /** 回滚成功后回调(清空 lastRestoreId)。 */
36
+ onRollbackDone?: () => void
37
+ }
38
+
39
+ type ConflictResolution = 'useRemote' | 'keepLocal' | 'skip'
40
+
41
+ /** 单条差异项的可变决策状态。 */
42
+ interface ItemState {
43
+ adopted: boolean
44
+ resolution?: ConflictResolution
45
+ }
46
+
47
+ export function SyncConfirmView(props: SyncConfirmViewProps): ReactNode {
48
+ const { api, syncSessionId, snapshotId, items, needsReview, compatibility, t, onCancel, onRollbackDone } = props;
49
+ // 逐项决策状态(初始 = defaultAdopt)
50
+ const [states, setStates] = useState<Record<string, ItemState>>(() => {
51
+ const init: Record<string, ItemState> = {};
52
+ for (const it of items) init[it.itemId] = { adopted: it.defaultAdopt, resolution: undefined };
53
+ return init;
54
+ });
55
+ // 执行阶段:'idle' | 'applying' | 'done' | 'failed' | 'cancelling'
56
+ const [phase, setPhase] = useState<'idle' | 'applying' | 'done' | 'failed' | 'cancelling'>('idle');
57
+ const [applyResult, setApplyResult] = useState<ApplyItemsResponse | null>(null);
58
+ const [error, setError] = useState<string | null>(null);
59
+
60
+ const summary = useMemo(() => summarizeConfirmItems(
61
+ items.map((it) => ({ ...it, adopt: states[it.itemId]?.adopted ?? it.defaultAdopt })),
62
+ ), [items, states]);
63
+
64
+ const setAdopted = (itemId: string, adopted: boolean): void => {
65
+ setStates((prev) => ({ ...prev, [itemId]: { ...prev[itemId], adopted } }));
66
+ };
67
+
68
+ const setResolution = (itemId: string, resolution: ConflictResolution): void => {
69
+ setStates((prev) => {
70
+ const existing: ItemState = prev[itemId] ?? { adopted: false, resolution: undefined };
71
+ return { ...prev, [itemId]: { ...existing, resolution } };
72
+ });
73
+ };
74
+
75
+ const runApply = async (): Promise<void> => {
76
+ // 校验冲突项必须已解决
77
+ const unresolved = items.find(
78
+ (it) => it.kind === 'Conflict' && (states[it.itemId]?.adopted === true) && states[it.itemId]?.resolution === undefined,
79
+ );
80
+ if (unresolved !== undefined) {
81
+ setError(t('syncflow.conflictUnresolved', { itemId: unresolved.itemId }));
82
+ return;
83
+ }
84
+ setPhase('applying');
85
+ setError(null);
86
+ try {
87
+ const adoptedMap = new Map<string, boolean>();
88
+ for (const it of items) {
89
+ adoptedMap.set(it.itemId, states[it.itemId]?.adopted ?? false);
90
+ }
91
+ const adoptions = items
92
+ .filter((it) => adoptedMap.get(it.itemId) === true)
93
+ .map((it) => {
94
+ const adoption: { itemId: string; adopt: boolean; resolution?: ConflictResolution } = { itemId: it.itemId, adopt: true };
95
+ const res = states[it.itemId]?.resolution;
96
+ if (it.kind === 'Conflict' && res !== undefined && res !== 'skip') adoption.resolution = res;
97
+ return adoption;
98
+ });
99
+ const result = await api.applyItems({ syncSessionId, adoptions });
100
+ setPhase(result.ok ? 'done' : 'failed');
101
+ setApplyResult(result);
102
+ } catch (err) {
103
+ setPhase('failed');
104
+ setError(err instanceof Error ? err.message : String(err));
105
+ }
106
+ };
107
+
108
+ const runCancel = async (): Promise<void> => {
109
+ setPhase('cancelling');
110
+ setError(null);
111
+ try {
112
+ await api.cancel(syncSessionId);
113
+ } catch { /* 取消失败无需打扰 */ }
114
+ onCancel();
115
+ };
116
+
117
+ const runRollback = async (restoreId: string): Promise<void> => {
118
+ setPhase('applying');
119
+ setError(null);
120
+ try {
121
+ await api.rollback({ restoreId });
122
+ setPhase('done');
123
+ setApplyResult(null);
124
+ onRollbackDone?.();
125
+ } catch (err) {
126
+ setPhase('failed');
127
+ setError(err instanceof Error ? err.message : String(err));
128
+ }
129
+ };
130
+
131
+ const busy = phase === 'applying' || phase === 'cancelling';
132
+
133
+ if (items.length === 0) {
134
+ return (
135
+ <Card>
136
+ <span className={css.groupLabel}>{t('syncflow.title')}</span>
137
+ <Banner kind="ok">{t('syncflow.empty')}</Banner>
138
+ <div className={css.actionRow}>
139
+ <Button disabled={busy} onClick={() => { void runCancel() }}>
140
+ {t('syncflow.cancel')}
141
+ </Button>
142
+ </div>
143
+ </Card>
144
+ );
145
+ }
146
+
147
+ return (
148
+ <Card>
149
+ <span className={css.groupLabel}>
150
+ {t('syncflow.title')}
151
+ {compatibility !== undefined && <Badge kind="info">{compatibility}</Badge>}
152
+ </span>
153
+ <Banner kind={needsReview ? 'warn' : 'info'}>
154
+ {needsReview ? t('syncflow.needsReviewBadge') : t('syncflow.diffCount', { count: String(summary.total) })}
155
+ </Banner>
156
+ <div className={css.statRow}>
157
+ <Badge kind="info">{t('syncflow.diffCount', { count: String(summary.total) })}</Badge>
158
+ <Badge kind="ok">{t('syncflow.adoptRemote')} {summary.adopted}</Badge>
159
+ {summary.error > 0 && <Badge kind="error">{severityLabel('error', api.t)} × {summary.error}</Badge>}
160
+ {summary.warning > 0 && <Badge kind="warn">{severityLabel('warning', api.t)} × {summary.warning}</Badge>}
161
+ </div>
162
+ <span className={css.hint}>{t('syncflow.adoptHint')}</span>
163
+
164
+ {/* 逐项差异列表 */}
165
+ <div className={css.reportList}>
166
+ {items.map((it) => {
167
+ const st = states[it.itemId] ?? { adopted: it.defaultAdopt };
168
+ const isConflict = it.kind === 'Conflict';
169
+ return (
170
+ <div key={it.itemId} className={css.statRow}>
171
+ <label className={css.checkboxRow}>
172
+ <input
173
+ type="checkbox"
174
+ checked={st.adopted}
175
+ disabled={busy}
176
+ onChange={(e) => { setAdopted(it.itemId, e.target.checked) }}
177
+ />
178
+ <span>{kindLabel(it.kind, api.t)}</span>
179
+ </label>
180
+ <Badge kind={it.severity === 'error' ? 'error' : it.severity === 'warning' ? 'warn' : 'info'}>
181
+ {severityLabel(it.severity, api.t)}
182
+ </Badge>
183
+ <span>{it.description}</span>
184
+ {isConflict && (
185
+ <ConflictResolver
186
+ item={it}
187
+ resolution={st.resolution}
188
+ busy={busy}
189
+ t={t}
190
+ onResolve={(r) => { setResolution(it.itemId, r) }}
191
+ />
192
+ )}
193
+ </div>
194
+ );
195
+ })}
196
+ </div>
197
+
198
+ {error !== null && <Banner kind="error">{error}</Banner>}
199
+
200
+ {/* 确认导入 / 取消 */}
201
+ {phase === 'idle' && (
202
+ <div className={css.actionRow}>
203
+ <Button variant="primary" disabled={busy || summary.adopted === 0} onClick={() => { void runApply() }}>
204
+ {t('syncflow.confirmImport')}
205
+ </Button>
206
+ <Button disabled={busy} onClick={() => { void runCancel() }}>
207
+ {t('syncflow.cancel')}
208
+ </Button>
209
+ </div>
210
+ )}
211
+
212
+ {/* 执行结果 */}
213
+ {(phase === 'done' || phase === 'failed') && applyResult !== null && (
214
+ <ApplyResultCard result={applyResult} busy={busy} t={t} onRollback={runRollback} />
215
+ )}
216
+ {(phase === 'done' || phase === 'failed') && applyResult === null && (
217
+ <Banner kind="ok">{t('syncflow.rollbackDone')}</Banner>
218
+ )}
219
+ </Card>
220
+ );
221
+ }
222
+
223
+ /* ---------------------------------------------------------------- 冲突内联解决 */
224
+
225
+ interface ConflictResolverProps {
226
+ item: SyncConfirmItem
227
+ resolution?: ConflictResolution
228
+ busy: boolean
229
+ t: TranslateNS<'config-manager-sync'>
230
+ onResolve: (r: ConflictResolution) => void
231
+ }
232
+
233
+ function ConflictResolver({ item, resolution, busy, t, onResolve }: ConflictResolverProps): ReactNode {
234
+ const conflict = item.conflict;
235
+ return (
236
+ <span className={css.rowActions}>
237
+ <span className={css.fieldLabel}>{t('syncflow.conflictTitle')}</span>
238
+ <Button variant="ghost" disabled={busy || resolution === 'keepLocal'} onClick={() => { onResolve('keepLocal') }}>
239
+ {resolution === 'keepLocal' ? `✓ ${t('syncflow.conflictUseLocal')}` : t('syncflow.conflictUseLocal')}
240
+ </Button>
241
+ <Button variant="primary" disabled={busy || resolution === 'useRemote'} onClick={() => { onResolve('useRemote') }}>
242
+ {resolution === 'useRemote' ? `✓ ${t('syncflow.conflictUseRemote')}` : t('syncflow.conflictUseRemote')}
243
+ </Button>
244
+ <Button variant="ghost" disabled={busy || resolution === 'skip'} onClick={() => { onResolve('skip') }}>
245
+ {resolution === 'skip' ? `✓ ${t('syncflow.conflictSkip')}` : t('syncflow.conflictSkip')}
246
+ </Button>
247
+ {conflict?.diff !== undefined && (
248
+ <details className={css.conflictDetail}>
249
+ <summary>{t('syncflow.diff')}</summary>
250
+ <pre className={css.diffScroll}>{conflict.diff}</pre>
251
+ </details>
252
+ )}
253
+ </span>
254
+ );
255
+ }
256
+
257
+ /* ---------------------------------------------------------------- 执行结果 */
258
+
259
+ interface ApplyResultCardProps {
260
+ result: ApplyItemsResponse
261
+ busy: boolean
262
+ t: TranslateNS<'config-manager-sync'>
263
+ onRollback: (restoreId: string) => Promise<void>
264
+ }
265
+
266
+ function ApplyResultCard({ result, busy, t, onRollback }: ApplyResultCardProps): ReactNode {
267
+ const ok = result.ok;
268
+ return (
269
+ <>
270
+ <Banner kind={ok ? 'ok' : 'error'}>
271
+ {ok ? t('syncflow.importDone', { n: String(result.applied.length) }) : t('syncflow.importFailed')}
272
+ </Banner>
273
+ {result.needsRestart && <Banner kind="warn">{t('syncflow.needsRestart')}</Banner>}
274
+ {result.applied.length > 0 && (
275
+ <div>
276
+ <span className={css.fieldLabel}>{t('syncflow.importedSections')}</span>
277
+ <div className={css.statRow}>
278
+ {result.applied.map((sid) => <Badge key={sid} kind="ok">{sid}</Badge>)}
279
+ </div>
280
+ </div>
281
+ )}
282
+ {result.warnings.length > 0 && (
283
+ <div>
284
+ <span className={css.fieldLabel}>{t('syncflow.importWarnings')}</span>
285
+ <ul className={css.warnList}>
286
+ {result.warnings.map((w, i) => <li key={i}>{w}</li>)}
287
+ </ul>
288
+ </div>
289
+ )}
290
+ {result.restoreId !== '' && (
291
+ <Button
292
+ variant="danger"
293
+ disabled={busy}
294
+ onClick={() => { void onRollback(result.restoreId) }}
295
+ >
296
+ {busy ? <Spinner label={t('syncflow.rollingBack')} /> : t('syncflow.rollback')}
297
+ </Button>
298
+ )}
299
+ </>
300
+ );
301
+ }