chore: 保存当前架构收口与 bug 修复快照
归档本轮 P0/P1 bug 修复、设计审查迁移、AI selection scope 收口与 stream contract 调整,并保留当前 05 主线迁移起点。
This commit is contained in:
@@ -2018,12 +2018,17 @@ fn build_tree_shell_html(
|
||||
|
||||
const getFileTreeRowDocumentId = (item) => {
|
||||
if (!item) return "";
|
||||
if (item.resourceMeta?.documentId) return item.resourceMeta.documentId;
|
||||
if (item.rowKind === "document" || item.rowKind === "markdown") return item.nodeId;
|
||||
if (item.rowKind === "index") return item.nodeId.replace(/^index:/, "");
|
||||
return "";
|
||||
};
|
||||
|
||||
const getFileTreeRowOwnerDocumentId = (item) => {
|
||||
if (!item) return "";
|
||||
if (item.resourceMeta?.documentId) return item.resourceMeta.documentId;
|
||||
return getFileTreeRowDocumentId(item);
|
||||
};
|
||||
|
||||
const getFileTreeRowAssetId = (item) => {
|
||||
if (!item) return "";
|
||||
if (item.resourceMeta?.assetId) return item.resourceMeta.assetId;
|
||||
@@ -2084,6 +2089,7 @@ fn build_tree_shell_html(
|
||||
rowKind: "root",
|
||||
nodeId: null,
|
||||
documentId: null,
|
||||
ownerDocumentId: null,
|
||||
assetId: null,
|
||||
};
|
||||
}
|
||||
@@ -2092,6 +2098,7 @@ fn build_tree_shell_html(
|
||||
rowKind: normalizeText(row.dataset.rowKind, "document"),
|
||||
nodeId: normalizeText(row.dataset.nodeId) || null,
|
||||
documentId: normalizeText(row.dataset.documentId) || null,
|
||||
ownerDocumentId: normalizeText(row.dataset.ownerDocumentId) || null,
|
||||
assetId: normalizeText(row.dataset.assetId) || null,
|
||||
};
|
||||
};
|
||||
@@ -2934,13 +2941,14 @@ fn build_tree_shell_html(
|
||||
const targetItem = targetRowId ? fileTreeRowById.get(targetRowId) : null;
|
||||
const target = targetItem
|
||||
? {
|
||||
rowId: targetItem.rowId,
|
||||
rowKind: targetItem.rowKind,
|
||||
nodeId: targetItem.nodeId,
|
||||
documentId: getFileTreeRowDocumentId(targetItem) || null,
|
||||
assetId: getFileTreeRowAssetId(targetItem) || null,
|
||||
}
|
||||
: { rowId: null, rowKind: "root", nodeId: null, documentId: null, assetId: null };
|
||||
rowId: targetItem.rowId,
|
||||
rowKind: targetItem.rowKind,
|
||||
nodeId: targetItem.nodeId,
|
||||
documentId: getFileTreeRowDocumentId(targetItem) || null,
|
||||
ownerDocumentId: getFileTreeRowOwnerDocumentId(targetItem) || null,
|
||||
assetId: getFileTreeRowAssetId(targetItem) || null,
|
||||
}
|
||||
: { rowId: null, rowKind: "root", nodeId: null, documentId: null, ownerDocumentId: null, assetId: null };
|
||||
if (sourceKind === "local_folder") {
|
||||
const pasted = await executeLocalFileTreeInternalDrop(
|
||||
target,
|
||||
@@ -3030,7 +3038,12 @@ fn build_tree_shell_html(
|
||||
if (event.key === "F2") {
|
||||
event.preventDefault();
|
||||
const rowId = item?.rowId || fileTreeFocusedRowId;
|
||||
if (rowId) beginInlineRename("filetree", rowId);
|
||||
const renameItem = rowId ? fileTreeRowById.get(rowId) : null;
|
||||
if (rowId && getFileTreeRowDocumentId(renameItem)) {
|
||||
beginInlineRename("filetree", rowId);
|
||||
} else {
|
||||
setLastAction("当前资源暂不支持重命名", "error");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (event.key === "ArrowDown") {
|
||||
@@ -3057,7 +3070,11 @@ fn build_tree_shell_html(
|
||||
event.preventDefault();
|
||||
if (item) {
|
||||
const documentId = getFileTreeRowDocumentId(item);
|
||||
if (documentId) handleNavigate(documentId);
|
||||
if (documentId) {
|
||||
handleNavigate(documentId);
|
||||
} else {
|
||||
openHydratedFileTreeItem(item);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -3219,7 +3236,7 @@ fn build_tree_shell_html(
|
||||
});
|
||||
}
|
||||
normalizedItems.slice().forEach((item) => {
|
||||
const itemDocumentId = getFileTreeRowDocumentId(item) || item.resourceMeta?.documentId || item.nodeId;
|
||||
const itemDocumentId = getFileTreeRowOwnerDocumentId(item) || item.nodeId;
|
||||
if (removedNodeIds.has(item.nodeId) || itemDocumentId === normalizedDocumentId) {
|
||||
removeTreeItemEverywhere(item);
|
||||
changed = true;
|
||||
@@ -4149,8 +4166,7 @@ fn build_tree_shell_html(
|
||||
rowKind === "markdown" ||
|
||||
rowKind === "document" ||
|
||||
rowKind === "folder" ||
|
||||
rowKind === "index" ||
|
||||
(localSource && rowKind === "asset");
|
||||
rowKind === "index";
|
||||
const canCopyCut =
|
||||
rowKind === "markdown" ||
|
||||
rowKind === "document" ||
|
||||
@@ -4282,7 +4298,9 @@ fn build_tree_shell_html(
|
||||
return;
|
||||
}
|
||||
if (kind === "rename") {
|
||||
if (target.rowId) beginInlineRename("filetree", target.rowId);
|
||||
if (target.rowId && getFileTreeRowDocumentId(item)) {
|
||||
beginInlineRename("filetree", target.rowId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (kind === "copy" || kind === "cut") {
|
||||
@@ -4639,8 +4657,14 @@ fn build_tree_shell_html(
|
||||
const id = inlineRenameState.id;
|
||||
const item = renameMode === "filetree" ? fileTreeRowById.get(id) : itemById.get(id);
|
||||
const documentId = renameMode === "filetree"
|
||||
? getFileTreeRowDocumentId(item) || item?.nodeId || id
|
||||
? getFileTreeRowDocumentId(item)
|
||||
: id;
|
||||
if (!documentId) {
|
||||
inlineRenameState = { mode: null, id: null, committing: false };
|
||||
setLastAction("当前资源暂不支持重命名", "error");
|
||||
renderTree();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await sendCommand({
|
||||
action: "rename",
|
||||
@@ -4953,6 +4977,7 @@ fn build_tree_shell_html(
|
||||
|
||||
const openHydratedFileTreeItem = (item) => {
|
||||
const documentId = getFileTreeRowDocumentId(item);
|
||||
const ownerDocumentId = getFileTreeRowOwnerDocumentId(item);
|
||||
const assetId = getFileTreeRowAssetId(item);
|
||||
if (item.rowKind === "document" || item.rowKind === "index") {
|
||||
handleNavigate(documentId || item.nodeId);
|
||||
@@ -4960,12 +4985,12 @@ fn build_tree_shell_html(
|
||||
}
|
||||
setLastAction(`准备打开资源 ${assetId || item.rowId}`);
|
||||
postToHost("tree.asset.open", {
|
||||
documentId: documentId || null,
|
||||
documentId: ownerDocumentId || null,
|
||||
assetId: assetId || null,
|
||||
objectIdentity: item.resourceMeta?.objectIdentity || null,
|
||||
target: { documentId: documentId || null },
|
||||
target: { documentId: ownerDocumentId || null },
|
||||
payload: {
|
||||
documentId: documentId || null,
|
||||
documentId: ownerDocumentId || null,
|
||||
assetId: assetId || null,
|
||||
rowId: item.rowId,
|
||||
rowKind: item.rowKind,
|
||||
@@ -5122,6 +5147,7 @@ fn build_tree_shell_html(
|
||||
const bindFileTreeRowEvents = (row, item) => {
|
||||
if (!(row instanceof HTMLElement) || !item) return;
|
||||
const documentId = getFileTreeRowDocumentId(item) || null;
|
||||
const ownerDocumentId = getFileTreeRowOwnerDocumentId(item) || null;
|
||||
const assetId = getFileTreeRowAssetId(item) || null;
|
||||
row.dataset.active = String(
|
||||
item.rowKind === "document" && documentId === currentActiveDocumentId
|
||||
@@ -5130,6 +5156,7 @@ fn build_tree_shell_html(
|
||||
row.dataset.rowId = item.rowId;
|
||||
row.dataset.rowKind = item.rowKind;
|
||||
row.dataset.documentId = documentId || "";
|
||||
row.dataset.ownerDocumentId = ownerDocumentId || "";
|
||||
row.dataset.assetId = assetId || "";
|
||||
row.dataset.objectIdentity = item.resourceMeta?.objectIdentity
|
||||
? JSON.stringify(item.resourceMeta.objectIdentity)
|
||||
@@ -5577,6 +5604,7 @@ fn build_tree_shell_html(
|
||||
|
||||
const openFileTreeItem = (item) => {
|
||||
const documentId = getFileTreeRowDocumentId(item);
|
||||
const ownerDocumentId = getFileTreeRowOwnerDocumentId(item);
|
||||
const assetId = getFileTreeRowAssetId(item);
|
||||
if (item.rowKind === "document" || item.rowKind === "index" || item.rowKind === "markdown") {
|
||||
handleNavigate(documentId || item.nodeId);
|
||||
@@ -5584,12 +5612,12 @@ fn build_tree_shell_html(
|
||||
}
|
||||
setLastAction(`准备打开资源 ${assetId || item.rowId}`);
|
||||
postToHost("tree.asset.open", {
|
||||
documentId: documentId || null,
|
||||
documentId: ownerDocumentId || null,
|
||||
assetId: assetId || null,
|
||||
objectIdentity: item.resourceMeta?.objectIdentity || null,
|
||||
target: { documentId: documentId || null },
|
||||
target: { documentId: ownerDocumentId || null },
|
||||
payload: {
|
||||
documentId: documentId || null,
|
||||
documentId: ownerDocumentId || null,
|
||||
assetId: assetId || null,
|
||||
rowId: item.rowId,
|
||||
rowKind: item.rowKind,
|
||||
@@ -5649,6 +5677,7 @@ fn build_tree_shell_html(
|
||||
const children = getSiblings(item.nodeId);
|
||||
const hasBranches = canExpandFileTreeRow(item) && children.length > 0;
|
||||
const documentId = getFileTreeRowDocumentId(item) || null;
|
||||
const ownerDocumentId = getFileTreeRowOwnerDocumentId(item) || null;
|
||||
const assetId = getFileTreeRowAssetId(item) || null;
|
||||
|
||||
const row = document.createElement("div");
|
||||
@@ -5661,6 +5690,7 @@ fn build_tree_shell_html(
|
||||
row.dataset.rowId = item.rowId;
|
||||
row.dataset.rowKind = item.rowKind;
|
||||
row.dataset.documentId = documentId || "";
|
||||
row.dataset.ownerDocumentId = ownerDocumentId || "";
|
||||
row.dataset.assetId = assetId || "";
|
||||
row.dataset.objectIdentity = item.resourceMeta?.objectIdentity
|
||||
? JSON.stringify(item.resourceMeta.objectIdentity)
|
||||
@@ -5769,15 +5799,17 @@ fn build_tree_shell_html(
|
||||
|
||||
const actions = document.createElement("div");
|
||||
actions.className = "tree-actions";
|
||||
actions.appendChild(
|
||||
createActionButton(
|
||||
ICONS.edit,
|
||||
"filetree-action-rename",
|
||||
`重命名 ${item.title}`,
|
||||
() => beginInlineRename("filetree", item.rowId),
|
||||
false,
|
||||
),
|
||||
);
|
||||
if (getFileTreeRowDocumentId(item)) {
|
||||
actions.appendChild(
|
||||
createActionButton(
|
||||
ICONS.edit,
|
||||
"filetree-action-rename",
|
||||
`重命名 ${item.title}`,
|
||||
() => beginInlineRename("filetree", item.rowId),
|
||||
false,
|
||||
),
|
||||
);
|
||||
}
|
||||
actions.appendChild(
|
||||
createActionButton(
|
||||
ICONS.more,
|
||||
@@ -7143,6 +7175,11 @@ mod tests {
|
||||
assert!(html.contains("tree.filetree.external-drop"));
|
||||
assert!(html.contains("\"rowKind\":\"asset_folder\""));
|
||||
assert!(html.contains("\"resourceMeta\""));
|
||||
assert!(html.contains("const getFileTreeRowOwnerDocumentId = (item) => {"));
|
||||
assert!(html.contains("row.dataset.ownerDocumentId = ownerDocumentId || \"\";"));
|
||||
assert!(html.contains("if (rowId && getFileTreeRowDocumentId(renameItem))"));
|
||||
assert!(html.contains("if (getFileTreeRowDocumentId(item))"));
|
||||
assert!(html.contains("documentId: ownerDocumentId || null"));
|
||||
assert!(html.contains("dragover"));
|
||||
assert!(html.contains("hydrateInitialFileTree"));
|
||||
assert!(html.contains("const usedRustInitialRenderer = hydrateInitialRenderer();"));
|
||||
@@ -7897,7 +7934,7 @@ mod tests {
|
||||
payload["result"]["documentId"],
|
||||
Value::String("page_child".into())
|
||||
);
|
||||
assert_eq!(payload["result"]["sortOrder"], Value::from(1));
|
||||
assert_eq!(payload["result"]["sortOrder"], Value::Null);
|
||||
assert_eq!(
|
||||
payload["result"]["execution"]["deletedCount"],
|
||||
Value::from(1)
|
||||
|
||||
Reference in New Issue
Block a user