# 4-46 [done][bug] FileTree 资源行被当成页面命令对象处理 v1

> 发现时间：2026-05-17
>
> 更新时间：2026-05-17
>
> 状态：`[done]`
>
> 关联主线：`04-tree-domain`

## 1. 问题定义

FileTree asset row 的 `resourceMeta` 同时带 `documentId` 和 `assetId`，但 tree shell 的部分交互会优先读取 `documentId`，从而把资源行当成页面行执行删除、复制、移动、重命名等页面命令。

这直接违反 Resource Tree / File Tree / Page Tree 的分层边界。

## 2. 证据

- [bridge-runtime/src/lib.rs](/mnt/Data1T/mnote/rust/crates/bridge-runtime/src/lib.rs:8499) 附近构造 asset row resource meta。
- [tree.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/tree.rs:2019) `getFileTreeRowDocumentId()` 优先返回资源行中的 `documentId`。
- [tree.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/tree.rs:2881) 键盘删除路径使用 documentId。
- [tree.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/tree.rs:2962) 剪贴板路径使用 documentId。
- [tree.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/tree.rs:4630) F2 重命名路径使用 documentId。

## 3. 影响

- 选中 mindmap / table / media asset 行后，可能误删或误重命名所属页面。
- 资源归属与页面结构命令混淆。
- `tree.resource.*` 的正式命令面无法成为资源操作唯一入口。

## 4. 建议修复

- FileTree row model 必须区分 `document row` 与 `resource row`，不要对 resource row 暴露页面 document command。
- Delete / F2 / copy / move 对资源行应走 `tree.resource.*`，或在未实现时显式禁用。
- 增加浏览器 smoke：资源行上 Delete、F2、Ctrl+C/X/V 不得触发页面命令。

## 5. 状态

已修复。

## 6. 修复内容

- `getFileTreeRowDocumentId()` 不再从 `resourceMeta.documentId` 读取资源 owner，只返回真正可作为页面命令目标的 document / markdown / index 行 ID。
- 新增 `getFileTreeRowOwnerDocumentId()`，资源打开与 owner 上下文继续使用 owner document ID。
- FileTree 资源行不再通过 F2 或行内编辑按钮进入页面重命名。
- 动态 filetree row DOM 增加 `data-owner-document-id`，`data-document-id` 仅表达页面命令目标。
- 初始 SSR filetree HTML 同步区分 `data-document-id` 与 `data-owner-document-id`，asset row 的 `data-document-id` / `data-doc-id` 保持为空。

## 7. 验证

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_shell::filetree_renderer::tests::tree_shell_filetree_renderer_outputs_initial_nested_html_contract -- --nocapture
```

结果：`1 passed`。

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web routes::tree::tests::tree_shell_filetree_mode_embeds_asset_state -- --nocapture
```

结果：`1 passed`。
