4-26 树rust-2

This commit is contained in:
lix-2026
2026-04-26 04:29:23 +08:00
parent 94631f3636
commit 338bb2e20f
58 changed files with 11718 additions and 1256 deletions
+47 -5
View File
@@ -3,10 +3,14 @@ import { api } from "./_generated/api";
import { v } from "convex/values";
import { requireUserId } from "./_utils/auth";
import { nowIso } from "./_utils/time";
import { collectSubtree } from "./_utils/documentTree";
import { buildParentById, collectSubtree, isAncestorOf } from "./_utils/documentTree";
import { enqueueIngestDocumentJob } from "./_utils/ingestJobs";
import { extractTextFromDocumentContent } from "./_utils/text";
import { getCanonicalDocumentByBusinessId, getCanonicalParentDocumentId } from "./_utils/documentRecord";
import {
getCanonicalDocumentByBusinessId,
getCanonicalParentDocumentId,
pickCanonicalDocumentRecordsByBusinessId,
} from "./_utils/documentRecord";
const accessScope = v.union(v.literal("private"), v.literal("shared"), v.literal("public"));
@@ -1378,8 +1382,35 @@ export const move = mutation({
const doc = await getCanonicalDocumentByBusinessId(ctx, args.id);
if (!doc) throw new Error("页面不存在");
if (doc.deleted_at != null) throw new Error("页面不存在");
if (doc.user_id !== userId) throw new Error("无权限");
const toParentId = args.parentId;
if (toParentId === doc.id) {
throw new Error("不能把页面移动到自身下面");
}
if (toParentId) {
const targetParentDoc = await getCanonicalDocumentByBusinessId<any>(ctx, toParentId);
if (!targetParentDoc || targetParentDoc.deleted_at != null || targetParentDoc.user_id !== userId) {
throw new Error("目标父页面不存在或无权限");
}
if (targetParentDoc.workspace_id !== doc.workspace_id) {
throw new Error("暂不支持跨工作空间移动页面");
}
const workspaceDocs = await ctx.db
.query("documents")
.withIndex("by_workspace", (q) => q.eq("workspace_id", doc.workspace_id))
.collect();
const canonicalWorkspaceDocs = pickCanonicalDocumentRecordsByBusinessId(workspaceDocs)
.filter((row) => row.user_id === userId)
.filter((row) => row.deleted_at == null);
const parentById = buildParentById(canonicalWorkspaceDocs);
if (isAncestorOf(doc.id, toParentId, parentById)) {
throw new Error("不能把页面移动到自己的后代下面");
}
}
// 说明:仅更新当前节点的 sort_order 会导致兄弟节点出现重复 sort_order
// 前端会按 sort_order + created_at 排序,结果常常表现为“拖拽无效/拖完又回弹”。
// 这里统一对目标父节点(以及跨父移动时的原父节点)做重新编号,保证 sort_order 唯一且连续。
@@ -1433,7 +1464,6 @@ export const move = mutation({
};
const fromParentId = (doc.parent_id ?? null) as string | null;
const toParentId = args.parentId;
if (fromParentId === toParentId) {
const siblings = await fetchSiblings(toParentId);
@@ -1441,7 +1471,13 @@ export const move = mutation({
const position = clampIndex(args.sortOrder, list.length);
list.splice(position, 0, doc);
await applyOrder(list, toParentId, doc._id);
return { ok: true, updated_at: ts };
return {
ok: true,
parent_id: toParentId,
sort_order: position,
workspace_id: doc.workspace_id,
updated_at: ts,
};
}
// 先重排原父节点,确保移动后原列表连续。
@@ -1454,7 +1490,13 @@ export const move = mutation({
newSiblings.splice(position, 0, doc);
await applyOrder(newSiblings, toParentId, doc._id);
return { ok: true, updated_at: ts };
return {
ok: true,
parent_id: toParentId,
sort_order: position,
workspace_id: doc.workspace_id,
updated_at: ts,
};
},
});