0.2.1 onlyoffice修复
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { randomUUID } from "crypto";
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
import { isConvexEnabled } from "@/lib/convex/enabled";
|
||||
import { requireAuthContext } from "@/lib/auth/authContext";
|
||||
import { getConvexHttpClient } from "@/lib/convex/server";
|
||||
import { api } from "@/lib/convex/api";
|
||||
import { getBlocksFromDocumentContent, findBlockInTree, withBlocksWrittenBack } from "@/lib/blocks";
|
||||
|
||||
type EmbedBlockPayload = {
|
||||
sourceDocumentId: string;
|
||||
blockId: string;
|
||||
targetDocumentId: string;
|
||||
position?: "end";
|
||||
};
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { sourceDocumentId, blockId, targetDocumentId }: EmbedBlockPayload = await request.json();
|
||||
|
||||
if (!sourceDocumentId || !blockId || !targetDocumentId) {
|
||||
return NextResponse.json({ error: "缺少参数" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (sourceDocumentId === targetDocumentId) {
|
||||
return NextResponse.json({ error: "禁止嵌入到当前页面" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const auth = requireAuthContext();
|
||||
const client = getConvexHttpClient();
|
||||
|
||||
const source = await client.query(api.documents.getContent, { userId: auth.userId, id: sourceDocumentId });
|
||||
if (!source) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
||||
const sourceBlocks = getBlocksFromDocumentContent(source.content);
|
||||
const hit = findBlockInTree(sourceBlocks, blockId);
|
||||
if (!hit) return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
||||
|
||||
const target = await client.query(api.documents.getContent, { userId: auth.userId, id: targetDocumentId });
|
||||
if (!target) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const targetBlocks = getBlocksFromDocumentContent(target.content);
|
||||
const referenceBlock = {
|
||||
id: randomUUID(),
|
||||
type: "blockReference",
|
||||
props: {
|
||||
sourceDocumentId,
|
||||
targetBlockId: blockId,
|
||||
display: "embed",
|
||||
},
|
||||
content: [],
|
||||
children: [],
|
||||
};
|
||||
|
||||
const nextBlocks = [...targetBlocks, referenceBlock];
|
||||
const payload = withBlocksWrittenBack(target.content, nextBlocks);
|
||||
await client.mutation(api.documents.updateContent, { userId: auth.userId, id: targetDocumentId, content: payload });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { data: sourceDoc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!sourceDoc) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const sourceBlocks = getBlocksFromDocumentContent(sourceDoc.content);
|
||||
if (!findBlockInTree(sourceBlocks, blockId)) {
|
||||
return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
||||
}
|
||||
|
||||
const { data: targetDoc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", targetDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!targetDoc) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const targetBlocks = getBlocksFromDocumentContent(targetDoc.content);
|
||||
const referenceBlock = {
|
||||
id: randomUUID(),
|
||||
type: "blockReference",
|
||||
props: {
|
||||
sourceDocumentId,
|
||||
targetBlockId: blockId,
|
||||
display: "embed",
|
||||
},
|
||||
content: [],
|
||||
children: [],
|
||||
};
|
||||
|
||||
const nextBlocks = [...targetBlocks, referenceBlock];
|
||||
const payload = withBlocksWrittenBack(targetDoc.content, nextBlocks);
|
||||
|
||||
const { error } = await supabase
|
||||
.from("documents")
|
||||
.update({ content: payload })
|
||||
.eq("id", targetDocumentId)
|
||||
.eq("user_id", session.user.id);
|
||||
|
||||
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
import { isConvexEnabled } from "@/lib/convex/enabled";
|
||||
import { requireAuthContext } from "@/lib/auth/authContext";
|
||||
import { getConvexHttpClient } from "@/lib/convex/server";
|
||||
import { api } from "@/lib/convex/api";
|
||||
import { getBlocksFromDocumentContent, findBlockInTree } from "@/lib/blocks";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
const sourceDocumentId = url.searchParams.get("sourceDocumentId") || "";
|
||||
const blockId = url.searchParams.get("blockId") || "";
|
||||
|
||||
if (!sourceDocumentId || !blockId) {
|
||||
return NextResponse.json({ error: "缺少参数" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const auth = requireAuthContext();
|
||||
const client = getConvexHttpClient();
|
||||
const doc = await client.query(api.documents.getContent, { userId: auth.userId, id: sourceDocumentId });
|
||||
if (!doc) return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
|
||||
const blocks = getBlocksFromDocumentContent(doc.content);
|
||||
const hit = findBlockInTree(blocks, blockId);
|
||||
if (!hit) return NextResponse.json({ error: "块不存在或无权限" }, { status: 404 });
|
||||
return NextResponse.json({ ok: true, block: hit.block });
|
||||
}
|
||||
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
if (!session) return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
|
||||
const { data: doc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!doc) return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const blocks = getBlocksFromDocumentContent(doc.content);
|
||||
const hit = findBlockInTree(blocks, blockId);
|
||||
if (!hit) return NextResponse.json({ error: "块不存在或无权限" }, { status: 404 });
|
||||
|
||||
return NextResponse.json({ ok: true, block: hit.block });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
import { isConvexEnabled } from "@/lib/convex/enabled";
|
||||
import { requireAuthContext } from "@/lib/auth/authContext";
|
||||
import { getConvexHttpClient } from "@/lib/convex/server";
|
||||
import { api } from "@/lib/convex/api";
|
||||
import { getBlocksFromDocumentContent, removeBlockSubtree, withBlocksWrittenBack } from "@/lib/blocks";
|
||||
|
||||
type MoveBlockPayload = {
|
||||
sourceDocumentId: string;
|
||||
blockId: string;
|
||||
targetDocumentId: string;
|
||||
position?: "end";
|
||||
};
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { sourceDocumentId, blockId, targetDocumentId }: MoveBlockPayload = await request.json();
|
||||
|
||||
if (!sourceDocumentId || !blockId || !targetDocumentId) {
|
||||
return NextResponse.json({ error: "缺少参数" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (sourceDocumentId === targetDocumentId) {
|
||||
// 说明:同页移动先不做“定位插入”,视为 no-op。
|
||||
return NextResponse.json({ ok: true, noop: true });
|
||||
}
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const auth = requireAuthContext();
|
||||
const client = getConvexHttpClient();
|
||||
|
||||
const source = await client.query(api.documents.getContent, { userId: auth.userId, id: sourceDocumentId });
|
||||
if (!source) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
||||
const sourceBlocks = getBlocksFromDocumentContent(source.content);
|
||||
const removedRes = removeBlockSubtree(sourceBlocks, blockId);
|
||||
if (!removedRes.removed) return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
||||
|
||||
const target = await client.query(api.documents.getContent, { userId: auth.userId, id: targetDocumentId });
|
||||
if (!target) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
||||
const targetBlocks = getBlocksFromDocumentContent(target.content);
|
||||
|
||||
const nextSourcePayload = withBlocksWrittenBack(source.content, removedRes.nextBlocks);
|
||||
const nextTargetPayload = withBlocksWrittenBack(target.content, [...targetBlocks, removedRes.removed]);
|
||||
|
||||
await client.mutation(api.documents.updateContent, { userId: auth.userId, id: sourceDocumentId, content: nextSourcePayload });
|
||||
await client.mutation(api.documents.updateContent, { userId: auth.userId, id: targetDocumentId, content: nextTargetPayload });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { data: sourceDoc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!sourceDoc) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const sourceBlocks = getBlocksFromDocumentContent(sourceDoc.content);
|
||||
const removedRes = removeBlockSubtree(sourceBlocks, blockId);
|
||||
if (!removedRes.removed) return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
||||
|
||||
const { data: targetDoc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", targetDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!targetDoc) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const targetBlocks = getBlocksFromDocumentContent(targetDoc.content);
|
||||
const nextSourcePayload = withBlocksWrittenBack(sourceDoc.content, removedRes.nextBlocks);
|
||||
const nextTargetPayload = withBlocksWrittenBack(targetDoc.content, [...targetBlocks, removedRes.removed]);
|
||||
|
||||
const { error: srcErr } = await supabase
|
||||
.from("documents")
|
||||
.update({ content: nextSourcePayload })
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id);
|
||||
if (srcErr) return NextResponse.json({ error: srcErr.message }, { status: 500 });
|
||||
|
||||
const { error: tgtErr } = await supabase
|
||||
.from("documents")
|
||||
.update({ content: nextTargetPayload })
|
||||
.eq("id", targetDocumentId)
|
||||
.eq("user_id", session.user.id);
|
||||
if (tgtErr) return NextResponse.json({ error: tgtErr.message }, { status: 500 });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
import { isConvexEnabled } from "@/lib/convex/enabled";
|
||||
import { requireAuthContext } from "@/lib/auth/authContext";
|
||||
import { getConvexHttpClient } from "@/lib/convex/server";
|
||||
import { api } from "@/lib/convex/api";
|
||||
import { getBlocksFromDocumentContent, replaceBlockInTree, withBlocksWrittenBack } from "@/lib/blocks";
|
||||
|
||||
type PatchPayload = {
|
||||
sourceDocumentId: string;
|
||||
blockId: string;
|
||||
nextBlock: unknown;
|
||||
};
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { sourceDocumentId, blockId, nextBlock }: PatchPayload = await request.json();
|
||||
|
||||
if (!sourceDocumentId || !blockId || !nextBlock) {
|
||||
return NextResponse.json({ error: "缺少参数" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const auth = requireAuthContext();
|
||||
const client = getConvexHttpClient();
|
||||
const doc = await client.query(api.documents.getContent, { userId: auth.userId, id: sourceDocumentId });
|
||||
if (!doc) return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const blocks = getBlocksFromDocumentContent(doc.content);
|
||||
const replaced = replaceBlockInTree(blocks, blockId, nextBlock as any);
|
||||
if (!replaced.ok) return NextResponse.json({ error: "块不存在或无权限" }, { status: 404 });
|
||||
|
||||
const payload = withBlocksWrittenBack(doc.content, replaced.nextBlocks);
|
||||
await client.mutation(api.documents.updateContent, { userId: auth.userId, id: sourceDocumentId, content: payload });
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
if (!session) return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
|
||||
const { data: doc } = await supabase
|
||||
.from("documents")
|
||||
.select("id,content,user_id")
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id)
|
||||
.single();
|
||||
if (!doc) return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
|
||||
|
||||
const blocks = getBlocksFromDocumentContent(doc.content);
|
||||
const replaced = replaceBlockInTree(blocks, blockId, nextBlock as any);
|
||||
if (!replaced.ok) return NextResponse.json({ error: "块不存在或无权限" }, { status: 404 });
|
||||
|
||||
const payload = withBlocksWrittenBack(doc.content, replaced.nextBlocks);
|
||||
const { error } = await supabase
|
||||
.from("documents")
|
||||
.update({ content: payload })
|
||||
.eq("id", sourceDocumentId)
|
||||
.eq("user_id", session.user.id);
|
||||
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user