dsh-config-manager 0.1.49 → 0.1.51

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/lib/client.js CHANGED
@@ -541,6 +541,8 @@ const CONFIG_MANAGER_API = {
541
541
  restore: "/api/dsh-config-manager/restore",
542
542
  backupSchedule: "/api/dsh-config-manager/backup-schedule",
543
543
  backupScheduleRun: "/api/dsh-config-manager/backup-schedule/run",
544
+ backupFiles: "/api/dsh-config-manager/backup-files",
545
+ backupFilesDelete: "/api/dsh-config-manager/backup-files/delete",
544
546
  starPrompt: "/api/dsh-config-manager/star-prompt"
545
547
  };
546
548
  /** 导出请求超时(ms):与 Host 半 ROUTE_TIMEOUT_MS 对齐,防止宿主卡死时 UI 无限等待 */
@@ -806,6 +808,18 @@ var ConfigManagerApi = class {
806
808
  body: JSON.stringify({})
807
809
  }), this.t);
808
810
  }
811
+ /** 列出导出目录(exports/*.zip)下的全部备份文件(时间倒序;含来源 auto/manual)。 */
812
+ async listBackupFiles() {
813
+ return (await readJson$3(await fetch(CONFIG_MANAGER_API.backupFiles), this.t)).files;
814
+ }
815
+ /** 删除一个备份文件(危险操作:不可恢复;仅限 exports 目录内 .zip)。 */
816
+ async deleteBackupFile(name) {
817
+ return readJson$3(await fetch(CONFIG_MANAGER_API.backupFilesDelete, {
818
+ method: "POST",
819
+ headers: { "content-type": "application/json" },
820
+ body: JSON.stringify({ name })
821
+ }), this.t);
822
+ }
809
823
  };
810
824
  //#endregion
811
825
  //#region src/ui/conflict-view.ts
@@ -2326,7 +2340,9 @@ function defaultSnapshotsState() {
2326
2340
  report: null,
2327
2341
  actionError: null,
2328
2342
  error: null,
2329
- backupDraft: null
2343
+ backupDraft: null,
2344
+ importBackup: null,
2345
+ subTab: "restore"
2330
2346
  };
2331
2347
  }
2332
2348
  function defaultState() {
@@ -2407,7 +2423,9 @@ function toSnapshotsStoreSlice(s) {
2407
2423
  report: s.report,
2408
2424
  actionError: s.actionError,
2409
2425
  error: s.error,
2410
- backupDraft: s.backupDraft
2426
+ backupDraft: s.backupDraft,
2427
+ importBackup: s.importBackup,
2428
+ subTab: s.subTab
2411
2429
  };
2412
2430
  }
2413
2431
  /**
@@ -2444,7 +2462,8 @@ function toPersistedState(state) {
2444
2462
  market: state.market,
2445
2463
  snapshots: {
2446
2464
  ...state.snapshots,
2447
- running: false
2465
+ running: false,
2466
+ importBackup: null
2448
2467
  }
2449
2468
  };
2450
2469
  }
@@ -2731,7 +2750,9 @@ var RunStore = class {
2731
2750
  snapshots: {
2732
2751
  ...defaultSnapshotsState(),
2733
2752
  ...parsed.snapshots,
2734
- running: false
2753
+ running: false,
2754
+ importBackup: null,
2755
+ subTab: parsed.snapshots.subTab === "files" ? "files" : "restore"
2735
2756
  }
2736
2757
  };
2737
2758
  if (this.state.import.containerEncrypted && this.state.import.phase !== "preview" && this.state.import.phase !== "decrypt-archive") this.state.import.phase = "decrypt-archive";
@@ -3042,7 +3063,7 @@ var RunStore = class {
3042
3063
  const runStore = new RunStore();
3043
3064
  //#endregion
3044
3065
  //#region \0config-manager-css:/home/runner/work/dsh-config-manager/dsh-config-manager/src/client/config-manager.module.css.js
3045
- const css = "._367UGW_section{height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);flex-direction:column;gap:10px;font-size:13px;display:flex}._367UGW_sectionHeader{flex:none;align-items:center;gap:10px;display:flex}._367UGW_viewTabs{border-bottom:1px solid var(--dsw-alias-border-l1);flex:1;gap:2px;display:flex}._367UGW_viewTab{color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;border-radius:6px 6px 0 0;padding:7px 14px;font-size:13px}._367UGW_viewTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._367UGW_viewTab[data-active]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary);font-weight:600}._367UGW_sectionBody{flex-direction:column;flex:1;min-height:0;display:flex;overflow-y:auto}._367UGW_viewBody{flex-direction:column;gap:12px;padding:4px 2px 16px;display:flex}._367UGW_sectionTitleBlock{flex-direction:column;gap:2px;display:flex}._367UGW_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:700}._367UGW_sectionSubtitle{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}._367UGW_primaryButton{color:var(--dsw-alias-label-primary-foreground);background:var(--dsw-alias-button-info-fill);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;align-items:center;gap:6px;padding:6px 14px;font-size:13px;font-weight:600;display:inline-flex}._367UGW_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}._367UGW_primaryButton:disabled{opacity:.5;cursor:default}._367UGW_ghostButton{color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;align-items:center;gap:6px;padding:5px 12px;font-size:12px;display:inline-flex}._367UGW_ghostButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._367UGW_ghostButton:disabled{opacity:.45;cursor:default}._367UGW_dangerButton{color:var(--dsw-alias-state-error-primary);border:1px solid var(--dsw-alias-state-error-primary);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;padding:5px 12px;font-size:12px}._367UGW_dangerButton:hover:not(:disabled){background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary-foreground)}._367UGW_dangerButton:disabled{opacity:.45;cursor:default}._367UGW_badge{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:999px;padding:1px 8px;font-size:11px;line-height:1.6;display:inline-block}._367UGW_badgeInfo{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}._367UGW_badgeOk{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._367UGW_badgeWarn{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._367UGW_badgeError{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._367UGW_banner{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;border-radius:8px;padding:8px 12px;font-size:12.5px;line-height:1.5}._367UGW_banner[data-kind=ok]{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._367UGW_banner[data-kind=error]{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._367UGW_banner[data-kind=info]{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}._367UGW_banner[data-kind=warn]{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._367UGW_card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;flex-direction:column;flex:none;gap:10px;padding:12px;display:flex}._367UGW_wizardCard{gap:14px}._367UGW_wizardCard ._367UGW_field{gap:8px}._367UGW_field{flex-direction:column;gap:5px;display:flex}._367UGW_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}._367UGW_input{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;outline:none;padding:7px 10px;font-family:inherit;font-size:13px}._367UGW_input:focus{border-color:var(--dsw-alias-state-business-primary)}._367UGW_input::placeholder{color:var(--dsw-alias-label-tertiary)}._367UGW_input:disabled{opacity:.55}._367UGW_select{-webkit-appearance:none;appearance:none;color:var(--dsw-alias-label-primary);background-color:var(--dsw-specific-input-major);background-image:linear-gradient(45deg, transparent 50%, var(--dsw-alias-label-secondary) 50%), linear-gradient(135deg, var(--dsw-alias-label-secondary) 50%, transparent 50%);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background-position:calc(100% - 17px) calc(50% - 1px),calc(100% - 12px) calc(50% - 1px);background-repeat:no-repeat;background-size:5px 5px,5px 5px;border-radius:8px;outline:none;max-width:100%;padding:7px 30px 7px 10px;font-family:inherit;font-size:13px}._367UGW_select:hover:not(:disabled){border-color:var(--dsw-alias-border-l1)}._367UGW_select:focus{border-color:var(--dsw-alias-state-business-primary)}._367UGW_select:disabled{opacity:.55;cursor:default}._367UGW_select option{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}._367UGW_hint{color:var(--dsw-alias-label-tertiary);font-size:11.5px;line-height:1.5}._367UGW_formError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px}._367UGW_checkboxRow{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:flex-start;gap:8px;font-size:13px;display:flex}._367UGW_checkboxRow input{flex:none;margin-top:2px}._367UGW_radioLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:13px;display:inline-flex}._367UGW_secretFields{grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px 12px;padding-top:4px;display:grid}._367UGW_hiddenFile{display:none}._367UGW_modeTabs{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;gap:2px;display:flex}._367UGW_modeTab{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px;font-size:12.5px}._367UGW_modeTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._367UGW_modeTab[data-active]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary);font-weight:600}._367UGW_modeHint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}._367UGW_groupList{flex-direction:column;gap:10px;display:flex}._367UGW_groupCard{gap:8px}._367UGW_groupHeader{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}._367UGW_groupLabel{color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:700}._367UGW_groupNote{color:var(--dsw-alias-label-tertiary);font-size:11.5px}._367UGW_groupItems{flex-direction:column;gap:6px;display:flex}._367UGW_categoryItem{flex-wrap:wrap;align-items:center;gap:8px;display:inline-flex}._367UGW_categoryName{font-weight:500}._367UGW_categoryDesc{color:var(--dsw-alias-label-tertiary);font-size:11.5px}._367UGW_optionsCard{gap:8px}._367UGW_optionsHeader{color:var(--dsw-alias-label-primary);letter-spacing:.02em;margin-bottom:2px;font-size:12px;font-weight:600}._367UGW_warnList{margin:4px 0 0;padding-left:18px}._367UGW_actionRow{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._367UGW_progressBlock{flex-direction:column;flex:none;gap:6px;display:flex}._367UGW_progressMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:12px;font-size:12px;display:flex}._367UGW_progressLabel{font-weight:600}._367UGW_progressDetail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}._367UGW_progressBadge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;align-items:center;gap:2px;padding:1px 8px;font-size:11px;line-height:18px;display:inline-flex}._367UGW_progressBadgeSection{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 14%, transparent);color:var(--dsw-alias-state-business-primary)}._367UGW_progressBadgeCount{background:color-mix(in srgb, var(--dsw-alias-state-info-primary) 14%, transparent);color:var(--dsw-alias-state-info-primary)}._367UGW_progressPercent{font-variant-numeric:tabular-nums;margin-left:auto}._367UGW_progressTrack{background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;height:8px;overflow:hidden}._367UGW_progressBar{background:var(--dsw-alias-state-business-primary);border-radius:999px;height:100%;transition:width .12s linear}._367UGW_progressBarDone{background:var(--dsw-alias-state-success-primary)}._367UGW_progressIndeterminate{width:40%;animation:1s ease-in-out infinite _367UGW_dshCmIndeterminate}._367UGW_logPanel{flex-direction:column;flex:none;gap:6px;display:flex}._367UGW_logHeader{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;font-size:12.5px;font-weight:600;display:flex}._367UGW_logJumpButton{font-family:var(--dsw-font-family);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:999px;padding:3px 8px;font-size:11px;line-height:1}._367UGW_logJumpButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._367UGW_logScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:200px;padding:2px 10px 6px;overflow-y:auto}._367UGW_logLine{white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);padding:1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:1.6}._367UGW_logEmpty{color:var(--dsw-alias-label-tertiary);padding:6px 0;font-size:11.5px}@keyframes _367UGW_dshCmIndeterminate{0%{margin-left:-40%}to{margin-left:100%}}._367UGW_reportView{flex-direction:column;gap:10px;display:flex}._367UGW_statRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}._367UGW_reportText{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;max-height:260px;color:var(--dsw-alias-label-primary);border-radius:8px;margin:0;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.6;overflow:auto}._367UGW_reportFooter{justify-content:flex-end;gap:8px;display:flex}._367UGW_rollbackBox{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-primary);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_rollbackBox ._367UGW_reportText{border-color:var(--dsw-alias-border-l2)}._367UGW_errorBanner{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_errorTitle{color:var(--dsw-alias-state-error-primary);font-size:13px;font-weight:700}._367UGW_errorReason{white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px}._367UGW_errorAction{color:var(--dsw-alias-label-secondary);font-size:12.5px}._367UGW_errorActionLabel{color:var(--dsw-alias-state-business-primary)}._367UGW_errorItem{color:var(--dsw-alias-label-tertiary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px}._367UGW_errorFooter{justify-content:flex-end;display:flex}._367UGW_errorList{flex-direction:column;gap:4px;display:flex}._367UGW_errorLine{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-state-error-primary);border-radius:6px;margin:0;padding:6px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._367UGW_conflictList{flex-direction:column;gap:10px;display:flex}._367UGW_conflictItem{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_conflictHead{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._367UGW_conflictId{color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:600}._367UGW_severityError{color:var(--dsw-alias-state-error-primary);border:1px solid var(--dsw-alias-state-error-primary);border-radius:999px;padding:0 6px;font-size:10.5px}._367UGW_conflictDetail{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);border-radius:6px;margin:0;padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._367UGW_conflictOptions{flex-wrap:wrap;gap:14px;display:flex}._367UGW_pathMappingList{flex-direction:column;gap:8px;display:flex}._367UGW_pathRow{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;padding:10px 12px;display:grid}._367UGW_pathOld,._367UGW_pathNew{flex-direction:column;gap:4px;min-width:0;display:flex}._367UGW_pathValue{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;overflow:hidden}._367UGW_pathIssueKind{color:var(--dsw-alias-state-warn-primary);font-size:10.5px}._367UGW_secretsList{flex-direction:column;gap:10px;display:flex}._367UGW_empty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:22px 12px;font-size:12.5px}._367UGW_spinnerWrap{align-items:center;gap:6px;display:inline-flex}._367UGW_spinner{border:2px solid var(--dsw-alias-state-business-primary);vertical-align:-1px;border-top-color:#0000;border-radius:50%;flex:none;width:11px;height:11px;animation:.8s linear infinite _367UGW_dshCmSpin;display:inline-block}._367UGW_spinnerLabel{color:var(--dsw-alias-label-secondary);font-size:12px}@keyframes _367UGW_dshCmSpin{to{transform:rotate(360deg)}}._367UGW_snapshotList{flex-direction:column;gap:2px;display:flex}._367UGW_snapshotRowHeader,._367UGW_snapshotRow{grid-template-columns:minmax(120px,1.2fr) minmax(140px,1.6fr) 90px 56px 56px;align-items:center;gap:8px;padding:6px 10px;font-size:12px;display:grid}._367UGW_snapshotRowHeader{color:var(--dsw-alias-label-tertiary);border-bottom:1px solid var(--dsw-alias-border-l1);font-size:11px}._367UGW_snapshotRow{text-align:left;width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px}._367UGW_snapshotRow:hover{background:var(--dsw-alias-interactive-bg-hover)}._367UGW_snapshotRow[data-active]{border-color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 10%, transparent)}._367UGW_warnText{color:var(--dsw-alias-state-warn-primary)}._367UGW_reportList{color:var(--dsw-alias-label-primary);flex-direction:column;gap:3px;margin:8px 0 4px;padding-left:18px;font-size:12px;display:flex}._367UGW_kindTag{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:1px 6px;font-size:10.5px;display:inline-block}._367UGW_planScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;height:280px;padding:2px 10px 8px;overflow-y:auto}._367UGW_planScroll ._367UGW_reportList{margin-top:6px}._367UGW_reportScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:220px;padding:2px 10px 6px;overflow-y:auto}._367UGW_reportScroll ._367UGW_reportList{margin-top:4px}._367UGW_confirmScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:280px;padding:2px 10px 6px;overflow-y:auto}._367UGW_confirmScroll ._367UGW_reportList{margin-top:4px;margin-bottom:0}._367UGW_pullScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;height:280px;padding:2px 10px 6px;overflow-y:auto}._367UGW_pullScroll ._367UGW_reportList{margin-top:4px;margin-bottom:0}._367UGW_rowActions{gap:8px;margin-top:10px;display:flex}._367UGW_diffScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;max-height:240px;color:var(--dsw-alias-label-primary);border-radius:8px;margin:0;padding:8px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.6;overflow:auto}._367UGW_aboutLinkRow{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._367UGW_aboutAuthor{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:4px 8px;font-size:13px;text-decoration:none;display:inline-flex}._367UGW_aboutAuthor:hover{background:var(--dsw-alias-interactive-bg-hover)}._367UGW_dialogMask{z-index:100;background:color-mix(in srgb, var(--dsw-alias-bg-base) 55%, transparent);justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}._367UGW_dialogCard{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:min(420px,100%);max-height:80vh;box-shadow:0 8px 24px color-mix(in srgb, var(--dsw-alias-bg-base) 40%, transparent);border-radius:10px;flex-direction:column;gap:10px;padding:14px;display:flex}._367UGW_dialogHeader{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:600}._367UGW_dialogBody{overscroll-behavior:contain;max-height:240px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;flex-direction:column;gap:10px;font-size:13px;line-height:1.6;display:flex;overflow-y:auto}._367UGW_dialogWide{width:min(560px,100%)}._367UGW_dialogBodyScroll{overscroll-behavior:contain;max-height:70vh;color:var(--dsw-alias-label-primary);white-space:normal;flex-direction:column;gap:10px;font-size:13px;line-height:1.6;display:flex;overflow-y:auto}._367UGW_dialogHeaderRow{justify-content:space-between;align-items:center;gap:10px;display:flex}._367UGW_dialogClose{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:2px 8px;font-size:16px;line-height:1}._367UGW_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-hover)}";
3066
+ const css = "._367UGW_section{height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);flex-direction:column;gap:10px;font-size:13px;display:flex}._367UGW_sectionHeader{flex:none;align-items:center;gap:10px;display:flex}._367UGW_viewTabs{border-bottom:1px solid var(--dsw-alias-border-l1);flex:1;gap:2px;display:flex}._367UGW_viewTab{color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;border-radius:6px 6px 0 0;padding:7px 14px;font-size:13px}._367UGW_viewTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._367UGW_viewTab[data-active]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary);font-weight:600}._367UGW_sectionBody{flex-direction:column;flex:1;min-height:0;display:flex;overflow-y:auto}._367UGW_viewBody{flex-direction:column;gap:12px;padding:4px 2px 16px;display:flex}._367UGW_sectionTitleBlock{flex-direction:column;gap:2px;display:flex}._367UGW_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:700}._367UGW_sectionSubtitle{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}._367UGW_primaryButton{color:var(--dsw-alias-label-primary-foreground);background:var(--dsw-alias-button-info-fill);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;align-items:center;gap:6px;padding:6px 14px;font-size:13px;font-weight:600;display:inline-flex}._367UGW_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}._367UGW_primaryButton:disabled{opacity:.5;cursor:default}._367UGW_ghostButton{color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;align-items:center;gap:6px;padding:5px 12px;font-size:12px;display:inline-flex}._367UGW_ghostButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._367UGW_ghostButton:disabled{opacity:.45;cursor:default}._367UGW_dangerButton{color:var(--dsw-alias-state-error-primary);border:1px solid var(--dsw-alias-state-error-primary);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;padding:5px 12px;font-size:12px}._367UGW_dangerButton:hover:not(:disabled){background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary-foreground)}._367UGW_dangerButton:disabled{opacity:.45;cursor:default}._367UGW_badge{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:999px;padding:1px 8px;font-size:11px;line-height:1.6;display:inline-block}._367UGW_badgeInfo{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}._367UGW_badgeOk{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._367UGW_badgeWarn{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._367UGW_badgeError{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._367UGW_banner{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;border-radius:8px;padding:8px 12px;font-size:12.5px;line-height:1.5}._367UGW_banner[data-kind=ok]{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._367UGW_banner[data-kind=error]{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._367UGW_banner[data-kind=info]{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}._367UGW_banner[data-kind=warn]{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._367UGW_card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;flex-direction:column;flex:none;gap:10px;padding:12px;display:flex}._367UGW_wizardCard{gap:14px}._367UGW_wizardCard ._367UGW_field{gap:8px}._367UGW_field{flex-direction:column;gap:5px;display:flex}._367UGW_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}._367UGW_input{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;outline:none;padding:7px 10px;font-family:inherit;font-size:13px}._367UGW_input:focus{border-color:var(--dsw-alias-state-business-primary)}._367UGW_input::placeholder{color:var(--dsw-alias-label-tertiary)}._367UGW_input:disabled{opacity:.55}._367UGW_select{-webkit-appearance:none;appearance:none;color:var(--dsw-alias-label-primary);background-color:var(--dsw-specific-input-major);background-image:linear-gradient(45deg, transparent 50%, var(--dsw-alias-label-secondary) 50%), linear-gradient(135deg, var(--dsw-alias-label-secondary) 50%, transparent 50%);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background-position:calc(100% - 17px) calc(50% - 1px),calc(100% - 12px) calc(50% - 1px);background-repeat:no-repeat;background-size:5px 5px,5px 5px;border-radius:8px;outline:none;max-width:100%;padding:7px 30px 7px 10px;font-family:inherit;font-size:13px}._367UGW_select:hover:not(:disabled){border-color:var(--dsw-alias-border-l1)}._367UGW_select:focus{border-color:var(--dsw-alias-state-business-primary)}._367UGW_select:disabled{opacity:.55;cursor:default}._367UGW_select option{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}._367UGW_hint{color:var(--dsw-alias-label-tertiary);font-size:11.5px;line-height:1.5}._367UGW_formError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px}._367UGW_checkboxRow{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:flex-start;gap:8px;font-size:13px;display:flex}._367UGW_checkboxRow input{flex:none;margin-top:2px}._367UGW_radioLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:13px;display:inline-flex}._367UGW_secretFields{grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px 12px;padding-top:4px;display:grid}._367UGW_hiddenFile{display:none}._367UGW_modeTabs{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;gap:2px;display:flex}._367UGW_modeTab{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px;font-size:12.5px}._367UGW_modeTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._367UGW_modeTab[data-active]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary);font-weight:600}._367UGW_modeHint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}._367UGW_groupList{flex-direction:column;gap:10px;display:flex}._367UGW_groupCard{gap:8px}._367UGW_groupHeader{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}._367UGW_groupLabel{color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:700}._367UGW_groupNote{color:var(--dsw-alias-label-tertiary);font-size:11.5px}._367UGW_groupItems{flex-direction:column;gap:6px;display:flex}._367UGW_categoryItem{flex-wrap:wrap;align-items:center;gap:8px;display:inline-flex}._367UGW_categoryName{font-weight:500}._367UGW_categoryDesc{color:var(--dsw-alias-label-tertiary);font-size:11.5px}._367UGW_optionsCard{gap:8px}._367UGW_optionsHeader{color:var(--dsw-alias-label-primary);letter-spacing:.02em;margin-bottom:2px;font-size:12px;font-weight:600}._367UGW_warnList{margin:4px 0 0;padding-left:18px}._367UGW_actionRow{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._367UGW_progressBlock{flex-direction:column;flex:none;gap:6px;display:flex}._367UGW_progressMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:12px;font-size:12px;display:flex}._367UGW_progressLabel{font-weight:600}._367UGW_progressDetail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}._367UGW_progressBadge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;align-items:center;gap:2px;padding:1px 8px;font-size:11px;line-height:18px;display:inline-flex}._367UGW_progressBadgeSection{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 14%, transparent);color:var(--dsw-alias-state-business-primary)}._367UGW_progressBadgeCount{background:color-mix(in srgb, var(--dsw-alias-state-info-primary) 14%, transparent);color:var(--dsw-alias-state-info-primary)}._367UGW_progressPercent{font-variant-numeric:tabular-nums;margin-left:auto}._367UGW_progressTrack{background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;height:8px;overflow:hidden}._367UGW_progressBar{background:var(--dsw-alias-state-business-primary);border-radius:999px;height:100%;transition:width .12s linear}._367UGW_progressBarDone{background:var(--dsw-alias-state-success-primary)}._367UGW_progressIndeterminate{width:40%;animation:1s ease-in-out infinite _367UGW_dshCmIndeterminate}._367UGW_logPanel{flex-direction:column;flex:none;gap:6px;display:flex}._367UGW_logHeader{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;font-size:12.5px;font-weight:600;display:flex}._367UGW_logJumpButton{font-family:var(--dsw-font-family);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:999px;padding:3px 8px;font-size:11px;line-height:1}._367UGW_logJumpButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._367UGW_logScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:200px;padding:2px 10px 6px;overflow-y:auto}._367UGW_logLine{white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);padding:1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:1.6}._367UGW_logEmpty{color:var(--dsw-alias-label-tertiary);padding:6px 0;font-size:11.5px}@keyframes _367UGW_dshCmIndeterminate{0%{margin-left:-40%}to{margin-left:100%}}._367UGW_reportView{flex-direction:column;gap:10px;display:flex}._367UGW_statRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}._367UGW_reportText{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;max-height:260px;color:var(--dsw-alias-label-primary);border-radius:8px;margin:0;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.6;overflow:auto}._367UGW_reportFooter{justify-content:flex-end;gap:8px;display:flex}._367UGW_rollbackBox{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-primary);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_rollbackBox ._367UGW_reportText{border-color:var(--dsw-alias-border-l2)}._367UGW_errorBanner{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_errorTitle{color:var(--dsw-alias-state-error-primary);font-size:13px;font-weight:700}._367UGW_errorReason{white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px}._367UGW_errorAction{color:var(--dsw-alias-label-secondary);font-size:12.5px}._367UGW_errorActionLabel{color:var(--dsw-alias-state-business-primary)}._367UGW_errorItem{color:var(--dsw-alias-label-tertiary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px}._367UGW_errorFooter{justify-content:flex-end;display:flex}._367UGW_errorList{flex-direction:column;gap:4px;display:flex}._367UGW_errorLine{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-state-error-primary);border-radius:6px;margin:0;padding:6px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._367UGW_conflictList{flex-direction:column;gap:10px;display:flex}._367UGW_conflictItem{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._367UGW_conflictHead{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._367UGW_conflictId{color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:600}._367UGW_severityError{color:var(--dsw-alias-state-error-primary);border:1px solid var(--dsw-alias-state-error-primary);border-radius:999px;padding:0 6px;font-size:10.5px}._367UGW_conflictDetail{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-secondary);border-radius:6px;margin:0;padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._367UGW_conflictOptions{flex-wrap:wrap;gap:14px;display:flex}._367UGW_pathMappingList{flex-direction:column;gap:8px;display:flex}._367UGW_pathRow{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;padding:10px 12px;display:grid}._367UGW_pathOld,._367UGW_pathNew{flex-direction:column;gap:4px;min-width:0;display:flex}._367UGW_pathValue{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;overflow:hidden}._367UGW_pathIssueKind{color:var(--dsw-alias-state-warn-primary);font-size:10.5px}._367UGW_secretsList{flex-direction:column;gap:10px;display:flex}._367UGW_empty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:22px 12px;font-size:12.5px}._367UGW_spinnerWrap{align-items:center;gap:6px;display:inline-flex}._367UGW_spinner{border:2px solid var(--dsw-alias-state-business-primary);vertical-align:-1px;border-top-color:#0000;border-radius:50%;flex:none;width:11px;height:11px;animation:.8s linear infinite _367UGW_dshCmSpin;display:inline-block}._367UGW_spinnerLabel{color:var(--dsw-alias-label-secondary);font-size:12px}@keyframes _367UGW_dshCmSpin{to{transform:rotate(360deg)}}._367UGW_snapshotList{flex-direction:column;gap:2px;display:flex}._367UGW_snapshotRowHeader,._367UGW_snapshotRow{grid-template-columns:minmax(120px,1.2fr) minmax(140px,1.6fr) 90px 56px 56px;align-items:center;gap:8px;padding:6px 10px;font-size:12px;display:grid}._367UGW_snapshotRowHeader{color:var(--dsw-alias-label-tertiary);border-bottom:1px solid var(--dsw-alias-border-l1);font-size:11px}._367UGW_snapshotRow{text-align:left;width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px}._367UGW_snapshotRow:hover{background:var(--dsw-alias-interactive-bg-hover)}._367UGW_snapshotRow[data-active]{border-color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 10%, transparent)}._367UGW_backupFileList{flex-direction:column;gap:4px;display:flex}._367UGW_backupFileRow{border:1px solid var(--dsw-alias-border-l1);border-radius:6px;flex-wrap:wrap;align-items:center;gap:10px;padding:6px 10px;display:flex}._367UGW_backupFileName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);flex:180px;font-size:12px;overflow:hidden}._367UGW_backupFileMeta{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}._367UGW_warnText{color:var(--dsw-alias-state-warn-primary)}._367UGW_reportList{color:var(--dsw-alias-label-primary);flex-direction:column;gap:3px;margin:8px 0 4px;padding-left:18px;font-size:12px;display:flex}._367UGW_kindTag{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:1px 6px;font-size:10.5px;display:inline-block}._367UGW_planScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;height:280px;padding:2px 10px 8px;overflow-y:auto}._367UGW_planScroll ._367UGW_reportList{margin-top:6px}._367UGW_reportScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:220px;padding:2px 10px 6px;overflow-y:auto}._367UGW_reportScroll ._367UGW_reportList{margin-top:4px}._367UGW_confirmScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;max-height:280px;padding:2px 10px 6px;overflow-y:auto}._367UGW_confirmScroll ._367UGW_reportList{margin-top:4px;margin-bottom:0}._367UGW_pullScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;height:280px;padding:2px 10px 6px;overflow-y:auto}._367UGW_pullScroll ._367UGW_reportList{margin-top:4px;margin-bottom:0}._367UGW_rowActions{gap:8px;margin-top:10px;display:flex}._367UGW_diffScroll{overscroll-behavior:contain;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;word-break:break-all;max-height:240px;color:var(--dsw-alias-label-primary);border-radius:8px;margin:0;padding:8px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.6;overflow:auto}._367UGW_aboutLinkRow{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._367UGW_aboutAuthor{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:4px 8px;font-size:13px;text-decoration:none;display:inline-flex}._367UGW_aboutAuthor:hover{background:var(--dsw-alias-interactive-bg-hover)}._367UGW_dialogMask{z-index:100;background:color-mix(in srgb, var(--dsw-alias-bg-base) 55%, transparent);justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}._367UGW_dialogCard{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:min(420px,100%);max-height:80vh;box-shadow:0 8px 24px color-mix(in srgb, var(--dsw-alias-bg-base) 40%, transparent);border-radius:10px;flex-direction:column;gap:10px;padding:14px;display:flex}._367UGW_dialogHeader{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:600}._367UGW_dialogBody{overscroll-behavior:contain;max-height:240px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;flex-direction:column;gap:10px;font-size:13px;line-height:1.6;display:flex;overflow-y:auto}._367UGW_dialogWide{width:min(560px,100%)}._367UGW_dialogBodyScroll{overscroll-behavior:contain;max-height:70vh;color:var(--dsw-alias-label-primary);white-space:normal;flex-direction:column;gap:10px;font-size:13px;line-height:1.6;display:flex;overflow-y:auto}._367UGW_dialogHeaderRow{justify-content:space-between;align-items:center;gap:10px;display:flex}._367UGW_dialogClose{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:2px 8px;font-size:16px;line-height:1}._367UGW_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-hover)}";
3046
3067
  const tagId = "dsh-config-manager/config-manager.module.css";
3047
3068
  if (typeof document !== "undefined" && document.querySelector("style[data-tag=\"dsh-config-manager/config-manager.module.css\"]") === null) {
3048
3069
  const tag = document.createElement("style");
@@ -3052,126 +3073,130 @@ if (typeof document !== "undefined" && document.querySelector("style[data-tag=\"
3052
3073
  document.head.appendChild(tag);
3053
3074
  }
3054
3075
  var config_manager_module_css_default = {
3055
- "progressLabel": "_367UGW_progressLabel",
3056
- "sectionHeader": "_367UGW_sectionHeader",
3057
- "dialogMask": "_367UGW_dialogMask",
3058
- "secretFields": "_367UGW_secretFields",
3059
- "badgeInfo": "_367UGW_badgeInfo",
3060
- "groupList": "_367UGW_groupList",
3061
- "progressMeta": "_367UGW_progressMeta",
3062
- "snapshotRowHeader": "_367UGW_snapshotRowHeader",
3063
- "banner": "_367UGW_banner",
3064
- "reportList": "_367UGW_reportList",
3065
- "optionsCard": "_367UGW_optionsCard",
3066
- "reportView": "_367UGW_reportView",
3076
+ "planScroll": "_367UGW_planScroll",
3077
+ "progressTrack": "_367UGW_progressTrack",
3078
+ "categoryDesc": "_367UGW_categoryDesc",
3079
+ "conflictOptions": "_367UGW_conflictOptions",
3080
+ "pathNew": "_367UGW_pathNew",
3081
+ "pathOld": "_367UGW_pathOld",
3082
+ "optionsHeader": "_367UGW_optionsHeader",
3083
+ "modeTabs": "_367UGW_modeTabs",
3084
+ "snapshotList": "_367UGW_snapshotList",
3085
+ "groupLabel": "_367UGW_groupLabel",
3086
+ "dialogBodyScroll": "_367UGW_dialogBodyScroll",
3087
+ "snapshotRow": "_367UGW_snapshotRow",
3088
+ "viewTabs": "_367UGW_viewTabs",
3089
+ "empty": "_367UGW_empty",
3090
+ "section": "_367UGW_section",
3091
+ "pathRow": "_367UGW_pathRow",
3092
+ "conflictId": "_367UGW_conflictId",
3093
+ "card": "_367UGW_card",
3094
+ "conflictItem": "_367UGW_conflictItem",
3067
3095
  "reportScroll": "_367UGW_reportScroll",
3068
- "errorItem": "_367UGW_errorItem",
3069
- "errorFooter": "_367UGW_errorFooter",
3070
- "errorTitle": "_367UGW_errorTitle",
3071
- "rowActions": "_367UGW_rowActions",
3072
- "actionRow": "_367UGW_actionRow",
3073
- "spinnerWrap": "_367UGW_spinnerWrap",
3074
- "badgeWarn": "_367UGW_badgeWarn",
3075
- "errorList": "_367UGW_errorList",
3076
- "groupCard": "_367UGW_groupCard",
3096
+ "spinner": "_367UGW_spinner",
3077
3097
  "progressIndeterminate": "_367UGW_progressIndeterminate",
3078
- "groupNote": "_367UGW_groupNote",
3079
- "pathOld": "_367UGW_pathOld",
3080
- "hint": "_367UGW_hint",
3081
3098
  "modeHint": "_367UGW_modeHint",
3082
- "pathMappingList": "_367UGW_pathMappingList",
3083
3099
  "progressBar": "_367UGW_progressBar",
3084
- "reportFooter": "_367UGW_reportFooter",
3085
- "spinner": "_367UGW_spinner",
3086
- "dshCmSpin": "_367UGW_dshCmSpin",
3087
- "secretsList": "_367UGW_secretsList",
3088
- "logLine": "_367UGW_logLine",
3089
- "conflictHead": "_367UGW_conflictHead",
3090
- "ghostButton": "_367UGW_ghostButton",
3091
- "sectionTitle": "_367UGW_sectionTitle",
3092
- "empty": "_367UGW_empty",
3093
- "dialogWide": "_367UGW_dialogWide",
3100
+ "diffScroll": "_367UGW_diffScroll",
3101
+ "banner": "_367UGW_banner",
3102
+ "conflictList": "_367UGW_conflictList",
3103
+ "errorLine": "_367UGW_errorLine",
3104
+ "dialogBody": "_367UGW_dialogBody",
3105
+ "actionRow": "_367UGW_actionRow",
3106
+ "errorList": "_367UGW_errorList",
3107
+ "confirmScroll": "_367UGW_confirmScroll",
3108
+ "wizardCard": "_367UGW_wizardCard",
3109
+ "sectionTitleBlock": "_367UGW_sectionTitleBlock",
3110
+ "groupItems": "_367UGW_groupItems",
3111
+ "errorItem": "_367UGW_errorItem",
3112
+ "spinnerWrap": "_367UGW_spinnerWrap",
3113
+ "progressMeta": "_367UGW_progressMeta",
3114
+ "input": "_367UGW_input",
3115
+ "hiddenFile": "_367UGW_hiddenFile",
3116
+ "logScroll": "_367UGW_logScroll",
3117
+ "backupFileMeta": "_367UGW_backupFileMeta",
3118
+ "viewTab": "_367UGW_viewTab",
3119
+ "errorAction": "_367UGW_errorAction",
3094
3120
  "logPanel": "_367UGW_logPanel",
3095
- "dialogHeader": "_367UGW_dialogHeader",
3096
- "badge": "_367UGW_badge",
3097
- "pathRow": "_367UGW_pathRow",
3121
+ "backupFileList": "_367UGW_backupFileList",
3122
+ "dialogHeaderRow": "_367UGW_dialogHeaderRow",
3123
+ "sectionTitle": "_367UGW_sectionTitle",
3124
+ "pathValue": "_367UGW_pathValue",
3125
+ "progressBarDone": "_367UGW_progressBarDone",
3126
+ "groupList": "_367UGW_groupList",
3127
+ "progressDetail": "_367UGW_progressDetail",
3128
+ "backupFileName": "_367UGW_backupFileName",
3129
+ "errorTitle": "_367UGW_errorTitle",
3130
+ "fieldLabel": "_367UGW_fieldLabel",
3131
+ "conflictHead": "_367UGW_conflictHead",
3132
+ "reportFooter": "_367UGW_reportFooter",
3133
+ "hint": "_367UGW_hint",
3098
3134
  "aboutLinkRow": "_367UGW_aboutLinkRow",
3099
- "snapshotList": "_367UGW_snapshotList",
3100
- "modeTab": "_367UGW_modeTab",
3101
- "logScroll": "_367UGW_logScroll",
3102
- "groupHeader": "_367UGW_groupHeader",
3103
- "progressBadge": "_367UGW_progressBadge",
3104
- "modeTabs": "_367UGW_modeTabs",
3105
- "dialogBody": "_367UGW_dialogBody",
3106
- "statRow": "_367UGW_statRow",
3107
- "field": "_367UGW_field",
3108
- "dialogBodyScroll": "_367UGW_dialogBodyScroll",
3109
- "radioLabel": "_367UGW_radioLabel",
3110
3135
  "progressBadgeSection": "_367UGW_progressBadgeSection",
3136
+ "badgeWarn": "_367UGW_badgeWarn",
3137
+ "aboutAuthor": "_367UGW_aboutAuthor",
3138
+ "errorBanner": "_367UGW_errorBanner",
3139
+ "select": "_367UGW_select",
3140
+ "kindTag": "_367UGW_kindTag",
3141
+ "categoryItem": "_367UGW_categoryItem",
3142
+ "reportView": "_367UGW_reportView",
3143
+ "spinnerLabel": "_367UGW_spinnerLabel",
3144
+ "logLine": "_367UGW_logLine",
3111
3145
  "progressPercent": "_367UGW_progressPercent",
3146
+ "badge": "_367UGW_badge",
3147
+ "reportText": "_367UGW_reportText",
3148
+ "dialogWide": "_367UGW_dialogWide",
3149
+ "errorReason": "_367UGW_errorReason",
3150
+ "formError": "_367UGW_formError",
3151
+ "reportList": "_367UGW_reportList",
3152
+ "badgeInfo": "_367UGW_badgeInfo",
3112
3153
  "dangerButton": "_367UGW_dangerButton",
3113
- "viewTab": "_367UGW_viewTab",
3114
- "categoryItem": "_367UGW_categoryItem",
3115
- "conflictId": "_367UGW_conflictId",
3116
- "groupItems": "_367UGW_groupItems",
3117
- "viewBody": "_367UGW_viewBody",
3154
+ "progressBlock": "_367UGW_progressBlock",
3155
+ "severityError": "_367UGW_severityError",
3118
3156
  "dialogClose": "_367UGW_dialogClose",
3157
+ "pathMappingList": "_367UGW_pathMappingList",
3158
+ "progressLabel": "_367UGW_progressLabel",
3159
+ "viewBody": "_367UGW_viewBody",
3160
+ "ghostButton": "_367UGW_ghostButton",
3161
+ "errorFooter": "_367UGW_errorFooter",
3162
+ "dialogHeader": "_367UGW_dialogHeader",
3163
+ "secretFields": "_367UGW_secretFields",
3164
+ "radioLabel": "_367UGW_radioLabel",
3165
+ "logJumpButton": "_367UGW_logJumpButton",
3166
+ "statRow": "_367UGW_statRow",
3167
+ "groupHeader": "_367UGW_groupHeader",
3168
+ "secretsList": "_367UGW_secretsList",
3169
+ "checkboxRow": "_367UGW_checkboxRow",
3170
+ "pullScroll": "_367UGW_pullScroll",
3171
+ "backupFileRow": "_367UGW_backupFileRow",
3172
+ "sectionHeader": "_367UGW_sectionHeader",
3173
+ "progressBadgeCount": "_367UGW_progressBadgeCount",
3174
+ "dshCmSpin": "_367UGW_dshCmSpin",
3175
+ "field": "_367UGW_field",
3176
+ "rollbackBox": "_367UGW_rollbackBox",
3177
+ "sectionBody": "_367UGW_sectionBody",
3178
+ "groupNote": "_367UGW_groupNote",
3179
+ "optionsCard": "_367UGW_optionsCard",
3119
3180
  "dialogCard": "_367UGW_dialogCard",
3120
- "snapshotRow": "_367UGW_snapshotRow",
3121
- "conflictOptions": "_367UGW_conflictOptions",
3122
3181
  "dshCmIndeterminate": "_367UGW_dshCmIndeterminate",
3123
- "optionsHeader": "_367UGW_optionsHeader",
3124
- "fieldLabel": "_367UGW_fieldLabel",
3125
- "formError": "_367UGW_formError",
3182
+ "errorActionLabel": "_367UGW_errorActionLabel",
3183
+ "groupCard": "_367UGW_groupCard",
3184
+ "warnList": "_367UGW_warnList",
3185
+ "progressBadge": "_367UGW_progressBadge",
3186
+ "warnText": "_367UGW_warnText",
3126
3187
  "logEmpty": "_367UGW_logEmpty",
3127
- "errorBanner": "_367UGW_errorBanner",
3188
+ "snapshotRowHeader": "_367UGW_snapshotRowHeader",
3189
+ "primaryButton": "_367UGW_primaryButton",
3128
3190
  "conflictDetail": "_367UGW_conflictDetail",
3129
- "conflictList": "_367UGW_conflictList",
3130
- "pathValue": "_367UGW_pathValue",
3131
- "errorReason": "_367UGW_errorReason",
3132
- "badgeOk": "_367UGW_badgeOk",
3133
- "wizardCard": "_367UGW_wizardCard",
3134
- "groupLabel": "_367UGW_groupLabel",
3135
- "reportText": "_367UGW_reportText",
3136
- "sectionSubtitle": "_367UGW_sectionSubtitle",
3137
- "dialogHeaderRow": "_367UGW_dialogHeaderRow",
3138
- "card": "_367UGW_card",
3139
- "viewTabs": "_367UGW_viewTabs",
3140
3191
  "categoryName": "_367UGW_categoryName",
3141
- "kindTag": "_367UGW_kindTag",
3142
- "errorAction": "_367UGW_errorAction",
3143
- "badgeError": "_367UGW_badgeError",
3144
- "progressBarDone": "_367UGW_progressBarDone",
3145
- "sectionBody": "_367UGW_sectionBody",
3146
- "progressTrack": "_367UGW_progressTrack",
3147
- "logJumpButton": "_367UGW_logJumpButton",
3148
- "categoryDesc": "_367UGW_categoryDesc",
3149
- "checkboxRow": "_367UGW_checkboxRow",
3150
- "progressDetail": "_367UGW_progressDetail",
3151
- "primaryButton": "_367UGW_primaryButton",
3152
- "errorActionLabel": "_367UGW_errorActionLabel",
3153
- "input": "_367UGW_input",
3154
- "warnText": "_367UGW_warnText",
3155
- "logHeader": "_367UGW_logHeader",
3156
- "progressBlock": "_367UGW_progressBlock",
3157
- "confirmScroll": "_367UGW_confirmScroll",
3158
- "sectionTitleBlock": "_367UGW_sectionTitleBlock",
3159
- "aboutAuthor": "_367UGW_aboutAuthor",
3160
- "section": "_367UGW_section",
3161
- "errorLine": "_367UGW_errorLine",
3162
- "hiddenFile": "_367UGW_hiddenFile",
3163
- "warnList": "_367UGW_warnList",
3164
- "rollbackBox": "_367UGW_rollbackBox",
3165
- "pullScroll": "_367UGW_pullScroll",
3166
- "diffScroll": "_367UGW_diffScroll",
3192
+ "sectionSubtitle": "_367UGW_sectionSubtitle",
3193
+ "rowActions": "_367UGW_rowActions",
3194
+ "dialogMask": "_367UGW_dialogMask",
3195
+ "badgeOk": "_367UGW_badgeOk",
3196
+ "modeTab": "_367UGW_modeTab",
3167
3197
  "pathIssueKind": "_367UGW_pathIssueKind",
3168
- "spinnerLabel": "_367UGW_spinnerLabel",
3169
- "conflictItem": "_367UGW_conflictItem",
3170
- "severityError": "_367UGW_severityError",
3171
- "pathNew": "_367UGW_pathNew",
3172
- "select": "_367UGW_select",
3173
- "planScroll": "_367UGW_planScroll",
3174
- "progressBadgeCount": "_367UGW_progressBadgeCount"
3198
+ "badgeError": "_367UGW_badgeError",
3199
+ "logHeader": "_367UGW_logHeader"
3175
3200
  };
3176
3201
  //#endregion
3177
3202
  //#region src/client/common/ui.tsx
@@ -4432,6 +4457,37 @@ function ImportWizardView({ api, t }) {
4432
4457
  } });
4433
4458
  if (fileInput.current !== null) fileInput.current.value = "";
4434
4459
  };
4460
+ /**
4461
+ * 一键导入(快照面板「备份文件 → 导入」):消费 runStore.snapshots.importBackup,
4462
+ * 跳过上传直接对宿主 exports 目录的 zipPath 执行 selectZip(analyze 零写入)。
4463
+ * 一次性瞬态:消费后立即清空,刷新/重挂载不会重放;与 onPickFile 共用
4464
+ * pickGeneration 竞态守卫(用户取消选择后晚到的分析结果丢弃)。
4465
+ */
4466
+ (0, react.useEffect)(() => {
4467
+ const req = runStore.getSnapshot().snapshots.importBackup;
4468
+ if (req === null) return;
4469
+ runStore.patch({ snapshots: { importBackup: null } });
4470
+ const generation = pickGeneration.current;
4471
+ runStore.patch({ import: {
4472
+ selectedFileName: req.name,
4473
+ uploading: true,
4474
+ error: null,
4475
+ decryptPassword: "",
4476
+ decryptRefs: [],
4477
+ archiveUnlocked: false,
4478
+ containerEncrypted: false
4479
+ } });
4480
+ wizard.selectZip(req.zipPath).then(() => {
4481
+ if (generation !== pickGeneration.current) return;
4482
+ runStore.syncWizard();
4483
+ }).catch((err) => {
4484
+ if (generation !== pickGeneration.current) return;
4485
+ runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } });
4486
+ runStore.syncWizard();
4487
+ }).finally(() => {
4488
+ if (generation === pickGeneration.current) runStore.patch({ import: { uploading: false } });
4489
+ });
4490
+ }, [api]);
4435
4491
  /** Compatibility → Preview */
4436
4492
  const goPreview = async () => {
4437
4493
  runStore.patch({ import: { error: null } });
@@ -5297,6 +5353,14 @@ function SnapshotsPanel({ api, t }) {
5297
5353
  const planGeneration = (0, react.useRef)(0);
5298
5354
  /** 执行恢复的二次确认弹窗开关(危险操作,DESIGN.md §8.11 场景) */
5299
5355
  const [confirmOpen, setConfirmOpen] = (0, react.useState)(false);
5356
+ /** 备份文件列表刷新信号:BackupScheduleCard「立即备份」完成后递增触发重载 */
5357
+ const [backupFilesTick, setBackupFilesTick] = (0, react.useState)(0);
5358
+ /** 二级 tab(备份文件 / 快照恢复):初始从 store 恢复,切换镜像 runStore(切一级 tab/刷新不丢) */
5359
+ const [subTab, setSubTab] = (0, react.useState)(() => runStore.getSnapshot().snapshots.subTab ?? "restore");
5360
+ const switchSubTab = (next) => {
5361
+ setSubTab(next);
5362
+ runStore.patch({ snapshots: { subTab: next } });
5363
+ };
5300
5364
  /**
5301
5365
  * 统一提交入口:更新 stateRef → 挂载时 setState → **总是**镜像进 runStore。
5302
5366
  * 关键:镜像不依赖 effect flush —— 异步操作(dry-run 计划/执行恢复)完成回调
@@ -5306,14 +5370,13 @@ function SnapshotsPanel({ api, t }) {
5306
5370
  const commit = (next) => {
5307
5371
  stateRef.current = next;
5308
5372
  if (mountedRef.current) setState(next);
5309
- const backupDraft = runStore.getSnapshot().snapshots.backupDraft;
5310
- runStore.patch({ snapshots: {
5311
- ...toSnapshotsStoreSlice({
5312
- ...next,
5313
- backupDraft
5314
- }),
5315
- backupDraft
5316
- } });
5373
+ const store = runStore.getSnapshot().snapshots;
5374
+ runStore.patch({ snapshots: toSnapshotsStoreSlice({
5375
+ ...next,
5376
+ backupDraft: store.backupDraft,
5377
+ importBackup: store.importBackup,
5378
+ subTab: store.subTab
5379
+ }) });
5317
5380
  };
5318
5381
  const patch = (p) => commit({
5319
5382
  ...stateRef.current,
@@ -5322,14 +5385,13 @@ function SnapshotsPanel({ api, t }) {
5322
5385
  /** 卸载时置挂载守卫 + 最后镜像一次(防止「最后一次改动后立即切 tab」时丢状态)。 */
5323
5386
  (0, react.useEffect)(() => () => {
5324
5387
  mountedRef.current = false;
5325
- const backupDraft = runStore.getSnapshot().snapshots.backupDraft;
5326
- runStore.patch({ snapshots: {
5327
- ...toSnapshotsStoreSlice({
5328
- ...stateRef.current,
5329
- backupDraft
5330
- }),
5331
- backupDraft
5332
- } });
5388
+ const store = runStore.getSnapshot().snapshots;
5389
+ runStore.patch({ snapshots: toSnapshotsStoreSlice({
5390
+ ...stateRef.current,
5391
+ backupDraft: store.backupDraft,
5392
+ importBackup: store.importBackup,
5393
+ subTab: store.subTab
5394
+ }) });
5333
5395
  }, []);
5334
5396
  const load = () => {
5335
5397
  patch({
@@ -5429,131 +5491,164 @@ function SnapshotsPanel({ api, t }) {
5429
5491
  title: t("snapshots.title"),
5430
5492
  subtitle: t("snapshots.hint")
5431
5493
  }),
5432
- state.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("snapshots.loading") }),
5433
- state.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Banner, {
5434
- kind: "error",
5435
- children: [state.error ?? t("common.unknownError"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5436
- variant: "primary",
5437
- onClick: load,
5438
- children: t("common.retry")
5494
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5495
+ className: config_manager_module_css_default.modeTabs,
5496
+ role: "tablist",
5497
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5498
+ type: "button",
5499
+ role: "tab",
5500
+ "aria-selected": subTab === "restore",
5501
+ "data-active": subTab === "restore" ? "" : void 0,
5502
+ className: config_manager_module_css_default.modeTab,
5503
+ onClick: () => {
5504
+ switchSubTab("restore");
5505
+ },
5506
+ children: t("snapshots.subTab.restore")
5507
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5508
+ type: "button",
5509
+ role: "tab",
5510
+ "aria-selected": subTab === "files",
5511
+ "data-active": subTab === "files" ? "" : void 0,
5512
+ className: config_manager_module_css_default.modeTab,
5513
+ onClick: () => {
5514
+ switchSubTab("files");
5515
+ },
5516
+ children: t("snapshots.subTab.files")
5439
5517
  })]
5440
5518
  }),
5441
- state.status === "ready" && state.metas.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { children: t("snapshots.empty") }),
5442
- state.status === "ready" && state.metas.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5443
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5444
- className: config_manager_module_css_default.snapshotList,
5445
- role: "listbox",
5446
- "aria-label": t("snapshots.selectHint"),
5447
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5448
- className: config_manager_module_css_default.snapshotRowHeader,
5449
- children: [
5450
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.createdAt") }),
5451
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.sourceZip") }),
5452
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.status") }),
5453
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.entries") }),
5454
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.plugins") })
5455
- ]
5456
- }), state.metas.map((meta) => {
5457
- const selected = meta.id === state.selectedId;
5458
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
5459
- type: "button",
5460
- role: "option",
5461
- "aria-selected": selected,
5462
- "data-active": selected ? "" : void 0,
5463
- className: config_manager_module_css_default.snapshotRow,
5464
- disabled: state.planning || state.running,
5465
- onClick: () => {
5466
- select(meta.id);
5467
- },
5468
- children: [
5469
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5470
- title: meta.id,
5471
- children: new Date(meta.createdAt).toLocaleString()
5472
- }),
5473
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5474
- title: meta.sourceZip,
5475
- children: meta.sourceZip
5476
- }),
5477
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
5478
- kind: statusBadgeKind(meta.status),
5479
- children: statusLabel(t, meta.status)
5480
- }) }),
5481
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meta.entryCount }),
5482
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meta.beforePluginCount })
5483
- ]
5484
- }, meta.id);
5519
+ subTab === "restore" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5520
+ state.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("snapshots.loading") }),
5521
+ state.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Banner, {
5522
+ kind: "error",
5523
+ children: [state.error ?? t("common.unknownError"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5524
+ variant: "primary",
5525
+ onClick: load,
5526
+ children: t("common.retry")
5485
5527
  })]
5486
5528
  }),
5487
- state.selectedId !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [state.planning && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("common.loading") }), state.plan !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, { children: [
5488
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionTitle, {
5489
- title: t("snapshots.planTitle"),
5490
- subtitle: summary()
5491
- }),
5492
- state.plan.actions.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { children: t("snapshots.noActions") }),
5493
- state.plan.actions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5494
- className: config_manager_module_css_default.planScroll,
5495
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
5496
- className: config_manager_module_css_default.reportList,
5497
- children: state.plan.actions.map((action, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
5498
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5499
- className: config_manager_module_css_default.kindTag,
5500
- children: actionKindLabel(action.kind)
5501
- }),
5502
- " ",
5503
- action.description,
5504
- action.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5505
- className: config_manager_module_css_default.hint,
5506
- children: [
5507
- "(",
5508
- action.detail,
5509
- ")"
5510
- ]
5511
- })
5512
- ] }, `plan-${i}`))
5513
- })
5529
+ state.status === "ready" && state.metas.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { children: t("snapshots.empty") }),
5530
+ state.status === "ready" && state.metas.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5532
+ className: config_manager_module_css_default.snapshotList,
5533
+ role: "listbox",
5534
+ "aria-label": t("snapshots.selectHint"),
5535
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5536
+ className: config_manager_module_css_default.snapshotRowHeader,
5537
+ children: [
5538
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.createdAt") }),
5539
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.sourceZip") }),
5540
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.status") }),
5541
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.entries") }),
5542
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("snapshots.plugins") })
5543
+ ]
5544
+ }), state.metas.map((meta) => {
5545
+ const selected = meta.id === state.selectedId;
5546
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
5547
+ type: "button",
5548
+ role: "option",
5549
+ "aria-selected": selected,
5550
+ "data-active": selected ? "" : void 0,
5551
+ className: config_manager_module_css_default.snapshotRow,
5552
+ disabled: state.planning || state.running,
5553
+ onClick: () => {
5554
+ select(meta.id);
5555
+ },
5556
+ children: [
5557
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5558
+ title: meta.id,
5559
+ children: new Date(meta.createdAt).toLocaleString()
5560
+ }),
5561
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5562
+ title: meta.sourceZip,
5563
+ children: meta.sourceZip
5564
+ }),
5565
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
5566
+ kind: statusBadgeKind(meta.status),
5567
+ children: statusLabel(t, meta.status)
5568
+ }) }),
5569
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meta.entryCount }),
5570
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meta.beforePluginCount })
5571
+ ]
5572
+ }, meta.id);
5573
+ })]
5514
5574
  }),
5515
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5516
- className: config_manager_module_css_default.rowActions,
5517
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5518
- variant: "danger",
5519
- disabled: state.running || state.plan.actions.every((a) => a.kind === "skip"),
5520
- onClick: () => {
5521
- setConfirmOpen(true);
5522
- },
5523
- children: state.running ? t("snapshots.executing") : t("snapshots.execute")
5575
+ state.selectedId !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [state.planning && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("common.loading") }), state.plan !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, { children: [
5576
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionTitle, {
5577
+ title: t("snapshots.planTitle"),
5578
+ subtitle: summary()
5579
+ }),
5580
+ state.plan.actions.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { children: t("snapshots.noActions") }),
5581
+ state.plan.actions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5582
+ className: config_manager_module_css_default.planScroll,
5583
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
5584
+ className: config_manager_module_css_default.reportList,
5585
+ children: state.plan.actions.map((action, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
5586
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5587
+ className: config_manager_module_css_default.kindTag,
5588
+ children: actionKindLabel(action.kind)
5589
+ }),
5590
+ " ",
5591
+ action.description,
5592
+ action.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5593
+ className: config_manager_module_css_default.hint,
5594
+ children: [
5595
+ "(",
5596
+ action.detail,
5597
+ ")"
5598
+ ]
5599
+ })
5600
+ ] }, `plan-${i}`))
5601
+ })
5602
+ }),
5603
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5604
+ className: config_manager_module_css_default.rowActions,
5605
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5606
+ variant: "danger",
5607
+ disabled: state.running || state.plan.actions.every((a) => a.kind === "skip"),
5608
+ onClick: () => {
5609
+ setConfirmOpen(true);
5610
+ },
5611
+ children: state.running ? t("snapshots.executing") : t("snapshots.execute")
5612
+ })
5613
+ }),
5614
+ state.actionError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Banner, {
5615
+ kind: "error",
5616
+ children: state.actionError
5524
5617
  })
5525
- }),
5526
- state.actionError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Banner, {
5527
- kind: "error",
5528
- children: state.actionError
5529
- })
5530
- ] })] }),
5531
- state.report !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5532
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionTitle, { title: t("snapshots.reportTitle") }),
5533
- reportLine(t("snapshots.restored"), state.report.restored, false),
5534
- reportLine(t("snapshots.removedPlugins"), state.report.removedPlugins, false),
5535
- reportLine(t("snapshots.manualHints"), state.report.manualHints, true),
5536
- reportLine(t("snapshots.failed"), state.report.failed.map((f) => `${f.item}: ${f.reason}`), true),
5537
- reportLine(t("snapshots.skipped"), state.report.skipped, false)
5538
- ] })
5539
- ] }),
5540
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BackupScheduleCard, {
5618
+ ] })] }),
5619
+ state.report !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5620
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionTitle, { title: t("snapshots.reportTitle") }),
5621
+ reportLine(t("snapshots.restored"), state.report.restored, false),
5622
+ reportLine(t("snapshots.removedPlugins"), state.report.removedPlugins, false),
5623
+ reportLine(t("snapshots.manualHints"), state.report.manualHints, true),
5624
+ reportLine(t("snapshots.failed"), state.report.failed.map((f) => `${f.item}: ${f.reason}`), true),
5625
+ reportLine(t("snapshots.skipped"), state.report.skipped, false)
5626
+ ] })
5627
+ ] }),
5628
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
5629
+ open: confirmOpen,
5630
+ title: t("snapshots.confirmTitle"),
5631
+ message: t("snapshots.confirmRestore"),
5632
+ confirmLabel: t("snapshots.execute"),
5633
+ cancelLabel: t("common.cancel"),
5634
+ danger: true,
5635
+ busy: state.running,
5636
+ onConfirm: execute,
5637
+ onCancel: () => {
5638
+ setConfirmOpen(false);
5639
+ }
5640
+ })
5641
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BackupFilesCard, {
5541
5642
  api,
5542
- t
5543
- }),
5544
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
5545
- open: confirmOpen,
5546
- title: t("snapshots.confirmTitle"),
5547
- message: t("snapshots.confirmRestore"),
5548
- confirmLabel: t("snapshots.execute"),
5549
- cancelLabel: t("common.cancel"),
5550
- danger: true,
5551
- busy: state.running,
5552
- onConfirm: execute,
5553
- onCancel: () => {
5554
- setConfirmOpen(false);
5643
+ t,
5644
+ refreshTick: backupFilesTick
5645
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BackupScheduleCard, {
5646
+ api,
5647
+ t,
5648
+ onBackupDone: () => {
5649
+ setBackupFilesTick((n) => n + 1);
5555
5650
  }
5556
- })
5651
+ })] })
5557
5652
  ]
5558
5653
  });
5559
5654
  }
@@ -5585,7 +5680,7 @@ function formatRunTime(iso) {
5585
5680
  * 状态自持;草稿镜像 runStore.snapshots.backupDraft(未保存修改切 tab/刷新保留),
5586
5681
  * 保存成功清草稿(宿主配置为权威)。
5587
5682
  */
5588
- function BackupScheduleCard({ api, t }) {
5683
+ function BackupScheduleCard({ api, t, onBackupDone }) {
5589
5684
  const [status, setStatus] = (0, react.useState)("loading");
5590
5685
  const [error, setError] = (0, react.useState)(null);
5591
5686
  const [draft, setDraft] = (0, react.useState)({
@@ -5662,11 +5757,13 @@ function BackupScheduleCard({ api, t }) {
5662
5757
  setFlash(null);
5663
5758
  setActionError(null);
5664
5759
  api.runBackupNow().then((res) => {
5665
- if (!mountedRef.current) return;
5666
- setSaved(res.schedule);
5667
- setLastRun(res.run.status);
5668
- setLastRunDetail(res.run.zip !== void 0 && res.run.zip !== "" ? res.run.zip : res.run.skipReason !== void 0 ? res.run.skipReason : formatRunTime(res.schedule.lastRunAt));
5669
- setRunning(false);
5760
+ if (mountedRef.current) {
5761
+ setSaved(res.schedule);
5762
+ setLastRun(res.run.status);
5763
+ setLastRunDetail(res.run.zip !== void 0 && res.run.zip !== "" ? res.run.zip : res.run.skipReason !== void 0 ? res.run.skipReason : formatRunTime(res.schedule.lastRunAt));
5764
+ setRunning(false);
5765
+ }
5766
+ onBackupDone?.();
5670
5767
  }, (err) => {
5671
5768
  if (!mountedRef.current) return;
5672
5769
  setRunning(false);
@@ -5771,6 +5868,175 @@ function BackupScheduleCard({ api, t }) {
5771
5868
  ]
5772
5869
  });
5773
5870
  }
5871
+ /**
5872
+ * 备份文件管理卡(m-backup-files):列出 exports/ 下的导出 ZIP(手动导出 + 定时备份),
5873
+ * 提供下载(复用 /download)/ 一键导入(切 Import tab + 注入 zipPath,向导直接分析)/
5874
+ * 删除(危险操作二次确认)。
5875
+ *
5876
+ * 状态组件自持(列表可随时重载,不持久化;与快照列表同级)。refreshTick 由父组件在
5877
+ * 「立即备份」完成后递增触发重载。安全:文件路径来自宿主受控 exports 目录;删除按钮
5878
+ * 恒走 ConfirmDialog(danger);导入 = 把 zipPath 交给现有导入向导(analyze 零写入,
5879
+ * 不经过上传)。
5880
+ */
5881
+ function BackupFilesCard({ api, t, refreshTick }) {
5882
+ const [status, setStatus] = (0, react.useState)("loading");
5883
+ const [error, setError] = (0, react.useState)(null);
5884
+ const [files, setFiles] = (0, react.useState)([]);
5885
+ const [deleting, setDeleting] = (0, react.useState)(false);
5886
+ const [confirmDelete, setConfirmDelete] = (0, react.useState)(null);
5887
+ const [actionError, setActionError] = (0, react.useState)(null);
5888
+ const mountedRef = (0, react.useRef)(true);
5889
+ const initialTick = (0, react.useRef)(refreshTick);
5890
+ (0, react.useEffect)(() => () => {
5891
+ mountedRef.current = false;
5892
+ }, []);
5893
+ const load = () => {
5894
+ setStatus("loading");
5895
+ setError(null);
5896
+ api.listBackupFiles().then((list) => {
5897
+ if (!mountedRef.current) return;
5898
+ setFiles(list);
5899
+ setStatus("ready");
5900
+ }, (err) => {
5901
+ if (!mountedRef.current) return;
5902
+ setStatus("error");
5903
+ setError(err instanceof Error ? err.message : String(err));
5904
+ });
5905
+ };
5906
+ (0, react.useEffect)(load, [api]);
5907
+ (0, react.useEffect)(() => {
5908
+ if (refreshTick === initialTick.current) return;
5909
+ load();
5910
+ }, [refreshTick]);
5911
+ const download = (file) => {
5912
+ setActionError(null);
5913
+ api.download(file.path, { saveDialog: true }).catch((err) => {
5914
+ if (!mountedRef.current) return;
5915
+ setActionError(err instanceof Error ? err.message : String(err));
5916
+ });
5917
+ };
5918
+ /** 一键导入:把备份文件 zipPath 交给现有导入向导(切 Import tab;向导挂载即分析) */
5919
+ const importBackup = (file) => {
5920
+ runStore.patch({
5921
+ view: "import",
5922
+ panel: null,
5923
+ snapshots: { importBackup: {
5924
+ zipPath: file.path,
5925
+ name: file.name
5926
+ } }
5927
+ });
5928
+ };
5929
+ const doDelete = () => {
5930
+ const file = confirmDelete;
5931
+ if (file === null || deleting) return;
5932
+ setDeleting(true);
5933
+ setActionError(null);
5934
+ api.deleteBackupFile(file.name).then(() => {
5935
+ setDeleting(false);
5936
+ setConfirmDelete(null);
5937
+ load();
5938
+ }, (err) => {
5939
+ setDeleting(false);
5940
+ setConfirmDelete(null);
5941
+ setActionError(err instanceof Error ? err.message : String(err));
5942
+ });
5943
+ };
5944
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, {
5945
+ className: config_manager_module_css_default.card,
5946
+ children: [
5947
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5948
+ className: config_manager_module_css_default.groupLabel,
5949
+ children: t("backupFiles.title")
5950
+ }),
5951
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5952
+ className: config_manager_module_css_default.hint,
5953
+ children: t("backupFiles.hint")
5954
+ }),
5955
+ status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spinner, { label: t("backupFiles.loading") }),
5956
+ status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Banner, {
5957
+ kind: "error",
5958
+ children: [error ?? t("common.unknownError"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5959
+ variant: "primary",
5960
+ onClick: load,
5961
+ children: t("common.retry")
5962
+ })]
5963
+ }),
5964
+ status === "ready" && files.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { children: t("backupFiles.empty") }),
5965
+ status === "ready" && files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5966
+ className: config_manager_module_css_default.backupFileList,
5967
+ role: "list",
5968
+ "aria-label": t("backupFiles.title"),
5969
+ children: files.map((file) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5970
+ className: config_manager_module_css_default.backupFileRow,
5971
+ role: "listitem",
5972
+ children: [
5973
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5974
+ className: config_manager_module_css_default.backupFileName,
5975
+ title: file.name,
5976
+ children: file.name
5977
+ }),
5978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
5979
+ kind: "info",
5980
+ children: file.source === "auto" ? t("backupFiles.source.auto") : t("backupFiles.source.manual")
5981
+ }),
5982
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5983
+ className: config_manager_module_css_default.backupFileMeta,
5984
+ children: formatBytes(file.sizeBytes)
5985
+ }),
5986
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5987
+ className: config_manager_module_css_default.backupFileMeta,
5988
+ children: new Date(file.mtimeMs).toLocaleString()
5989
+ }),
5990
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5991
+ className: config_manager_module_css_default.actionRow,
5992
+ children: [
5993
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
5994
+ disabled: deleting,
5995
+ onClick: () => {
5996
+ download(file);
5997
+ },
5998
+ children: t("backupFiles.download")
5999
+ }),
6000
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
6001
+ disabled: deleting,
6002
+ onClick: () => {
6003
+ importBackup(file);
6004
+ },
6005
+ children: t("backupFiles.import")
6006
+ }),
6007
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
6008
+ variant: "danger",
6009
+ disabled: deleting,
6010
+ onClick: () => {
6011
+ setConfirmDelete(file);
6012
+ },
6013
+ children: t("backupFiles.delete")
6014
+ })
6015
+ ]
6016
+ })
6017
+ ]
6018
+ }, file.name))
6019
+ }),
6020
+ actionError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Banner, {
6021
+ kind: "error",
6022
+ children: actionError
6023
+ }),
6024
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
6025
+ open: confirmDelete !== null,
6026
+ title: t("backupFiles.deleteConfirmTitle"),
6027
+ message: confirmDelete !== null ? t("backupFiles.deleteConfirm", { name: confirmDelete.name }) : void 0,
6028
+ confirmLabel: t("backupFiles.delete"),
6029
+ cancelLabel: t("common.cancel"),
6030
+ danger: true,
6031
+ busy: deleting,
6032
+ onConfirm: doDelete,
6033
+ onCancel: () => {
6034
+ setConfirmDelete(null);
6035
+ }
6036
+ })
6037
+ ]
6038
+ });
6039
+ }
5774
6040
  //#endregion
5775
6041
  //#region src/client/sync/sync-api.ts
5776
6042
  /** 同步端点常量(与 Host 半 src/index.ts API 常量保持一致) */
@@ -11074,7 +11340,7 @@ const zh$2 = {
11074
11340
  "section.description": "导出 / 导入 / 迁移 DSH 配置(备份不含密钥,加密备份可选)",
11075
11341
  "view.export": "导出备份",
11076
11342
  "view.import": "导入恢复",
11077
- "view.snapshots": "快照恢复",
11343
+ "view.snapshots": "备份与快照",
11078
11344
  "view.sync": "远程同步",
11079
11345
  "view.market": "配置市场",
11080
11346
  "view.about": "关于",
@@ -11167,8 +11433,10 @@ const zh$2 = {
11167
11433
  "import.paths.old": "原路径",
11168
11434
  "import.paths.new": "新路径",
11169
11435
  "import.paths.unresolved": "还有 {count} 条路径未映射",
11170
- "snapshots.title": "快照恢复",
11171
- "snapshots.hint": "恢复到导入前状态:整文件还原 settings/patch、卸载导入期间新增插件、补偿被修改文件。执行前会把当前文件备份到快照的 pre-restore 目录。",
11436
+ "snapshots.title": "备份与快照",
11437
+ "snapshots.hint": "导出备份 = 便携 ZIP(下载 / 一键导入 / 删除,含定时全量备份);快照恢复 = 恢复到导入前状态:整文件还原 settings/patch、卸载导入期间新增插件、补偿被修改文件,执行前会把当前文件备份到快照的 pre-restore 目录。",
11438
+ "snapshots.subTab.restore": "快照恢复",
11439
+ "snapshots.subTab.files": "备份文件",
11172
11440
  "snapshots.empty": "暂无快照。执行导入时会自动创建安全快照。",
11173
11441
  "snapshots.loading": "加载快照中…",
11174
11442
  "snapshots.selectHint": "选择快照以预览恢复计划(dry-run,零写入):",
@@ -11213,6 +11481,18 @@ const zh$2 = {
11213
11481
  "backupSchedule.status.failed": "失败",
11214
11482
  "backupSchedule.loading": "加载定时备份设置…",
11215
11483
  "backupSchedule.error": "定时备份设置加载失败",
11484
+ "backupFiles.title": "备份文件",
11485
+ "backupFiles.hint": "导出产物(手动导出与定时备份)统一在此管理:可下载到本机、直接导入恢复,或删除。定时备份自动保留最近 10 个。",
11486
+ "backupFiles.empty": "暂无备份文件。手动导出或启用定时备份后此处会列出。",
11487
+ "backupFiles.loading": "加载备份文件…",
11488
+ "backupFiles.error": "备份文件加载失败",
11489
+ "backupFiles.source.auto": "定时备份",
11490
+ "backupFiles.source.manual": "手动导出",
11491
+ "backupFiles.download": "下载",
11492
+ "backupFiles.import": "导入",
11493
+ "backupFiles.delete": "删除",
11494
+ "backupFiles.deleteConfirmTitle": "删除备份文件",
11495
+ "backupFiles.deleteConfirm": "确认删除备份文件「{name}」?此操作不可恢复。",
11216
11496
  "report.export.title": "导出完成",
11217
11497
  "report.import.title": "导入结果",
11218
11498
  "report.rollback.title": "回滚报告",
@@ -11245,7 +11525,7 @@ const en$2 = {
11245
11525
  "section.description": "Export / import / migrate DSH configuration (backups exclude secrets; encrypted backups optional)",
11246
11526
  "view.export": "Export",
11247
11527
  "view.import": "Import",
11248
- "view.snapshots": "Snapshots & Restore",
11528
+ "view.snapshots": "Backup & Snapshots",
11249
11529
  "view.sync": "Remote Sync",
11250
11530
  "view.market": "Marketplace",
11251
11531
  "view.about": "About",
@@ -11338,8 +11618,10 @@ const en$2 = {
11338
11618
  "import.paths.old": "Original path",
11339
11619
  "import.paths.new": "New path",
11340
11620
  "import.paths.unresolved": "{count} path(s) unmapped",
11341
- "snapshots.title": "Snapshot Restore",
11342
- "snapshots.hint": "Restore to the pre-import state: whole-file restore of settings/patch, uninstall plugins added during import, compensate modified files. Current files are backed up to the snapshot's pre-restore folder before any change.",
11621
+ "snapshots.title": "Backup & Snapshots",
11622
+ "snapshots.hint": "Export backups = portable ZIPs (download / one-click import / delete, incl. scheduled full backups). Snapshot restore = back to the pre-import state: whole-file restore of settings/patch, uninstall plugins added during import, compensate modified files; current files are backed up to the snapshot's pre-restore folder first.",
11623
+ "snapshots.subTab.restore": "Snapshot Restore",
11624
+ "snapshots.subTab.files": "Backup Files",
11343
11625
  "snapshots.empty": "No snapshots yet. A safety snapshot is created automatically on import.",
11344
11626
  "snapshots.loading": "Loading snapshots…",
11345
11627
  "snapshots.selectHint": "Select a snapshot to preview its restore plan (dry-run, zero writes):",
@@ -11384,6 +11666,18 @@ const en$2 = {
11384
11666
  "backupSchedule.status.failed": "Failed",
11385
11667
  "backupSchedule.loading": "Loading scheduled backup settings…",
11386
11668
  "backupSchedule.error": "Failed to load scheduled backup settings",
11669
+ "backupFiles.title": "Backup Files",
11670
+ "backupFiles.hint": "All export artifacts (manual exports and scheduled backups) are managed here: download to your machine, import to restore, or delete. Scheduled backups auto-keep the latest 10.",
11671
+ "backupFiles.empty": "No backup files yet. They appear here after a manual export or once scheduled backups are enabled.",
11672
+ "backupFiles.loading": "Loading backup files…",
11673
+ "backupFiles.error": "Failed to load backup files",
11674
+ "backupFiles.source.auto": "Scheduled",
11675
+ "backupFiles.source.manual": "Manual",
11676
+ "backupFiles.download": "Download",
11677
+ "backupFiles.import": "Import",
11678
+ "backupFiles.delete": "Delete",
11679
+ "backupFiles.deleteConfirmTitle": "Delete backup file",
11680
+ "backupFiles.deleteConfirm": "Delete backup file \"{name}\"? This cannot be undone.",
11387
11681
  "report.export.title": "Export Complete",
11388
11682
  "report.import.title": "Import Result",
11389
11683
  "report.rollback.title": "Rollback Report",