import { randomUUID } from "crypto"; import { NextResponse } from "next/server"; import { createSupabaseRouteClient } from "@/lib/supabase/server"; import { ensureDefaultWorkspace, resolveActiveWorkspaceId } from "@/lib/workspaces"; import type { Json } from "@/types/supabase"; import { composeContentWithBlocks, extractBlocksFromContent } from "@/lib/document-content"; export async function POST(request: Request) { try { return await handleCreateRequest(request); } catch (error) { console.error("创建页面失败", error); const message = error instanceof Error ? error.message : "创建页面失败,请稍后再试"; return NextResponse.json({ error: message }, { status: 500 }); } } async function handleCreateRequest(request: Request) { const supabase = await createSupabaseRouteClient(); const { data: { session }, } = await supabase.auth.getSession(); if (!session) { return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { parentId }: { parentId?: string | null } = await request.json(); await ensureDefaultWorkspace(supabase, session.user.id, session.user.email ?? "我的空间"); let workspaceId: string | null = null; let parentContent: Json | null = null; let accessScope: "private" | "shared" | "public" = "private"; if (parentId) { const { data: parentDoc, error: parentError } = await supabase .from("documents") .select("workspace_id,access_scope,content,user_id") .eq("id", parentId) .eq("user_id", session.user.id) .single(); if (parentError || !parentDoc) { return NextResponse.json({ error: "父页面不存在或无权限" }, { status: 404 }); } workspaceId = parentDoc.workspace_id; accessScope = (parentDoc.access_scope ?? "private") as typeof accessScope; parentContent = parentDoc.content; } else { workspaceId = await resolveActiveWorkspaceId(supabase, session.user.id); if (!workspaceId) { return NextResponse.json({ error: "缺少目标工作空间" }, { status: 400 }); } } if (!workspaceId) { return NextResponse.json({ error: "缺少目标工作空间" }, { status: 400 }); } const siblingQuery = supabase .from("documents") .select("id", { head: true, count: "exact" }) .eq("workspace_id", workspaceId); if (parentId) { siblingQuery.eq("parent_id", parentId); } else { siblingQuery.is("parent_id", null); } const { count: siblingCount = 0, error: countError } = await siblingQuery; if (countError) { return NextResponse.json({ error: countError.message }, { status: 500 }); } const { data, error } = await supabase .from("documents") .insert({ user_id: session.user.id, parent_id: parentId ?? null, workspace_id: workspaceId, title: "无标题", content: { blocks: [] }, access_scope: accessScope, sort_order: siblingCount, }) .select( "id,title,parent_id,sort_order,is_starred,created_at,updated_at,workspace_id,access_scope,is_template", ) .single(); if (error) { return NextResponse.json({ error: error.message }, { status: 400 }); } if (parentId && data) { const existingBlocks = extractBlocksFromContent(parentContent); const pageReferenceBlock = { id: randomUUID(), type: "pageReference", props: { pageId: data.id, title: data.title ?? "无标题", }, }; const nextBlocks = [...existingBlocks, pageReferenceBlock as Json]; const payload = composeContentWithBlocks(parentContent, nextBlocks); const timestamp = new Date().toISOString(); const { error: parentUpdateError } = await supabase .from("documents") .update({ content: payload, updated_at: timestamp }) .eq("id", parentId) .eq("user_id", session.user.id); if (parentUpdateError) { return NextResponse.json({ error: parentUpdateError.message }, { status: 500 }); } } return NextResponse.json(data); }