import { NextResponse } from "next/server"; import { createSupabaseRouteClient } from "@/lib/supabase/server"; import path from "path"; import { promises as fs } from "fs"; interface DuplicatePayload { documentId: string; } const documentsBaseDir = path.join(process.cwd(), "public", "documents"); async function ensureDocumentScaffold(id: string, title: string | null) { const folder = path.join(documentsBaseDir, id); const indexFile = path.join(folder, "index.md"); await fs.mkdir(folder, { recursive: true }); const safeTitle = title && title.trim() ? title.trim() : "无标题"; const content = `# ${safeTitle}\n`; await fs.writeFile(indexFile, content, "utf8"); } async function copyMindmapIfExists(sourceId: string, targetId: string) { try { const srcDir = path.join(documentsBaseDir, sourceId); const destDir = path.join(documentsBaseDir, targetId); const entries = await fs.readdir(srcDir); const mindmapFiles = entries.filter((name) => name === "mindmap.json" || /^mindmap-.+\\.json$/i.test(name)); if (mindmapFiles.length === 0) return; await fs.mkdir(destDir, { recursive: true }); await Promise.all( mindmapFiles.map(async (name) => { try { const buf = await fs.readFile(path.join(srcDir, name)); await fs.writeFile(path.join(destDir, name), buf); } catch { // ignore } }), ); } catch { // 如果源不存在则忽略 } } export async function POST(request: Request) { const supabase = await createSupabaseRouteClient(); const { data: { session }, } = await supabase.auth.getSession(); if (!session) { return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { documentId }: DuplicatePayload = await request.json(); if (!documentId) { return NextResponse.json({ error: "缺少 documentId" }, { status: 400 }); } const { data: sourceDoc, error: sourceError } = await supabase .from("documents") .select("id,title,content,parent_id,workspace_id,access_scope") .eq("id", documentId) .eq("user_id", session.user.id) .single(); if (sourceError || !sourceDoc) { return NextResponse.json({ error: "页面不存在或无权访问" }, { status: 404 }); } const siblingQuery = supabase .from("documents") .select("id", { head: true, count: "exact" }) .eq("workspace_id", sourceDoc.workspace_id); if (sourceDoc.parent_id) { siblingQuery.eq("parent_id", sourceDoc.parent_id); } else { siblingQuery.is("parent_id", null); } const { count: rawSiblingCount, error: countError } = await siblingQuery; const siblingCount = rawSiblingCount ?? 0; if (countError) { return NextResponse.json({ error: countError.message }, { status: 500 }); } const fallbackTitle = sourceDoc.title?.trim() && sourceDoc.title.trim().length > 0 ? sourceDoc.title.trim() : "无标题"; const duplicatedTitle = `${fallbackTitle} 副本`; const { data: duplicated, error: duplicateError } = await supabase .from("documents") .insert({ user_id: session.user.id, workspace_id: sourceDoc.workspace_id, parent_id: sourceDoc.parent_id, access_scope: sourceDoc.access_scope ?? "private", title: duplicatedTitle, content: sourceDoc.content, sort_order: siblingCount, }) .select("id,title,parent_id,sort_order") .single(); if (duplicateError || !duplicated) { return NextResponse.json( { error: duplicateError?.message ?? "复制失败" }, { status: 500 }, ); } await ensureDocumentScaffold(duplicated.id, duplicated.title ?? duplicatedTitle); await copyMindmapIfExists(sourceDoc.id, duplicated.id); return NextResponse.json(duplicated); }