Skip to content

fix(scan): report per-item import outcomes and bind preferred version (#39) - #40

Open
yukitakasama wants to merge 1 commit into
dsh-plugins:mainfrom
yukitakasama:fix/39-scan-import-report
Open

fix(scan): report per-item import outcomes and bind preferred version (#39)#40
yukitakasama wants to merge 1 commit into
dsh-plugins:mainfrom
yukitakasama:fix/39-scan-import-report

Conversation

@yukitakasama

Copy link
Copy Markdown
Contributor

TL;DR (EN)

Fixes the two defects from issue #39 in the scan/import wizard (Settings → 导入本机环境, added by #31 / #34): importing a local version/source directory never created an instance and silently reported success, and the auto-registered ~/.dsh home (id home-user-dsh) could never be turned into instances because its profiles were disabled. This PR makes every import outcome explicit (per-item added / skipped / failed + reason), re-enables profiles of already-known homes, and binds new instances to the version the user actually picked instead of blindly using the first one.

改动内容

后端(src-tauri/src/scan.rs

  • ImportReport 新增逐项明细 items: Vec<ImportItem>kind: home|version|instancenamestatus: added|skipped|failedreason),保留原有四计数字段兼容旧前端;失败不再静默 continue
    • 版本目录不存在 / HOME 目录不存在 → failed + 原因「目录不存在」
    • 版本 / HOME / 同名实例已存在 → skipped + 原因(幂等行为保留,仍计入 skipped_known
    • 版本登记成功 → added(版本本身不是实例;前端会明确提示)
  • ImportScannedInput 新增可选 preferred_version_dir(issue Scan/import wizard: importing a local source dir silently creates no instance, and the auto-registered ~/.dsh home can never be discovered in instance management #39 R3):实例创建时优先绑定用户所选版本目录(前端传第一个添加的版本);指定但未在 config 中 → 该实例 failed 并跳过创建,不再静默绑定错误版本;未指定时回落第一个已知版本;无任何版本时实例仍创建但附带警告原因「未绑定版本,请在实例编辑器中指定」
  • 核心逻辑抽为纯函数 apply_import(&mut Config, &ImportScannedInput) -> ImportReport,命令层 import_scanned 仅做 clone / 调用 / save_state,便于单元测试

前端

  • components/ImportScanDialog.vue
  • views/Instances.vue:表格上方新增「已登记但无实例的 HOME」提示条(列出 home 名 + 跳转设置页导入向导的入口),问题 2 的「在实例管理中不可见」有了明确出口
  • api/types.tsImportItemImportReport.itemsImportScannedInput.preferredVersionDir 类型同步
  • locales/zh-CN.json / en-US.json:新增 importScan.itemAdded/itemSkipped/itemFailed/versionNotInstance/doneWithFailures/removeVersioninstances.homesWithoutInstances*,两语言键集同步

测试(scan.rs #[cfg(test)]

  • import_versions_only_never_creates_instances_and_reports_items:仅导入版本 → 0 实例,逐项 added(回归问题 1)
  • import_missing_dirs_fail_per_item_instead_of_silently_skipping:不存在的版本/HOME 目录 → failed + 原因
  • import_creates_instances_and_binds_preferred_version:home+profile → 实例绑定 preferred_version_dir 对应版本
  • import_preferred_version_missing_fails_instances:所选版本不可用 → 实例 failed、不创建(回归 R3)
  • import_is_idempotent_and_counts_skips:重复导入不产生重复实例,skipped_known 计数正确
  • import_without_any_version_creates_instance_with_warning:无版本时实例创建 + 警告原因

验证

  • cargo test --workspace --locked(Windows cargo 1.97.0):118 passed / 0 failed(含上述 6 个新增用例)
  • cargo clippy --workspace --all-targets --locked -D warnings:0 警告
  • cargo fmt --check:通过
  • pnpm build(vue-tsc + vite):通过

Notes

  • 「实例管理页按 home 一键建实例」的快捷入口(任务树 3.1 方案 C)留作后续增强,本期以逐项报告 + 提示条 + 向导内解除禁用覆盖问题 2 的核心诉求
  • 修复行为说明已附于本 PR 描述;标签需仓库维护者添加

Issue dsh-plugins#39 (scan/import wizard defects):

- ImportReport gains a per-item items breakdown (kind/name/status/reason)
  so failures are never silent anymore: missing dirs, already-known
  entries and unbound versions are each reported instead of a bare
  continue.
- The wizard now passes preferredVersionDir (the first version the user
  added); newly created instances bind to it. When the picked version is
  not in the config, instances are skipped with a failed item instead of
  silently binding the wrong (first) version. Without any version the
  instance is still created, marked with a warning reason.
- ImportScanDialog: already_known homes are no longer disabled (problem 2)
  and their web/tui profiles are default-selected again; the import
  summary renders the per-item list (added/skipped/failed + reason) and
  the version rows get a remove button; the toast switches to a warning
  when any item failed.
- Instances.vue: registered homes that have no instances are surfaced
  above the table with a link to the import wizard.
- i18n: zh-CN / en-US updated with the new importScan / instances keys.
@Gu-ZT

Gu-ZT commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

请求修改(request changes)

方向与 issue #39 的两个缺陷都对得上,后端 apply_import 的拆分(import_scanned 只做持久化包装)与 5 个新单测质量都不错。但实测发现 1 处必须修复的缺陷。

阻塞项:浏览器预览(mock)下导入直接报错

src/api/types.tsImportReport.items 声明为必填ImportScanDialog.vue 也直接消费:

const result = await api.importScanned({...})
const failed = result.items.filter((i) => i.status === 'failed').length   // ImportScanDialog.vue:135

但本 PR 没有改动 src/api/index.ts,mock 仍返回旧结构:

case 'import_scanned':
  return { homes_added: 1, versions_added: 0, instances_added: 2, skipped_known: 0 } as T

后果:result.itemsundefinedresult.items.filterTypeError,被 doImportcatch 吞成 Message.error,浏览器预览里「导入所选」永远失败、且 importResult 明细区不渲染。这条 mock 在预览里是唯一数据源,属于本仓库既定的「mock 必须与命令同步」约定。

最小修复:mock 的 import_scanneditems(按上面的样例数据返回 home/version/instance 三种 kind 的混合结果即可),顺带让预览能看到新明细 UI。

非阻塞建议

  1. ImportScanDialog.vue:36 const itemStatusOf = (status: ImportItem['status']) => status 定义后从未使用(vue-tsc 不报未使用变量,所以 CI 看不出),建议删除。
  2. ImportScanDialog.vue:110-117versionItemLabel(item) !== itemLabel(item.status) 是用「拼好的字符串回比一次」来判定版本项,可读性差;等价于 item.kind === 'version' && item.status === 'added',建议直接写该条件(并删掉 versionItemLabel)。
  3. Instances.vuehomesWithoutInstances 对「WSL HOME / 用户自建 HOME」也会提示「还没有实例」,若希望只提示启动器自动登记的那类,可加条件;当前行为可接受,仅提示确认。
  4. preferredVersionDir: versions.value[0]?.dir ?? null 把「列表第一个」当作默认绑定版本;UI 上「移除」按钮可删除首项,此时默认版本会静默变成第二项。建议在 UI 上明确标注哪一项会成为新实例的默认版本(否则用户难以预期 R3 的行为)。

验证情况

  • 已本地核对 diff 与 pr-40 内容:scan.rsapply_import/ImportItem/preferred_version_dir 三条路径(added/skipped/failed)与 5 个新测试(含 import_preferred_version_missing_fails_instancesimport_is_idempotent_and_counts_skips)逐段读过,逻辑自洽。
  • 已确认 mock 未同步(git diff main...pr-40 -- src/api/index.ts 为空)。
  • CI 4/4 通过(Quality linux/macos/windows + Integration checks),未复现本地构建。

修好阻塞项(补 mock items)即可合入。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants