Files
mnote/wolai-frontend/src/app/api/mindmap-ai/assets/route.ts
T
2026-01-15 20:54:21 +08:00

119 lines
3.5 KiB
TypeScript

import { NextResponse } from "next/server";
import { createSupabaseRouteClient } from "@/lib/supabase/server";
import { detectLocalMindmapFiles } from "@/lib/server/mindmap-files";
import type { MediaAsset } from "@/types/media";
import path from "path";
import { promises as fs } from "fs";
export const dynamic = "force-dynamic";
type AgentAssetItem = {
kind: "media" | "local-mindmap" | "test-pdf";
id: string;
title: string;
fileUrl: string;
mimeType?: string | null;
assetType?: string | null;
fileName?: string | null;
};
const TEST_DIR = path.join(process.cwd(), "test");
async function listTestPdfs(): Promise<AgentAssetItem[]> {
try {
const entries = await fs.readdir(TEST_DIR);
return entries
.filter((name) => name.toLowerCase().endsWith(".pdf"))
.slice(0, 200)
.map((name) => ({
kind: "test-pdf" as const,
id: `test-pdf:${name}`,
title: name,
fileUrl: `/api/mindmap-ai/test-pdf?name=${encodeURIComponent(name)}`,
mimeType: "application/pdf",
assetType: "file",
fileName: name,
}));
} catch {
return [];
}
}
export async function GET(request: Request) {
const supabase = await createSupabaseRouteClient();
const {
data: { session },
} = await supabase.auth.getSession();
if (!session) {
return NextResponse.json({ error: "未登录" }, { status: 401 });
}
const { searchParams } = new URL(request.url);
const documentId = String(searchParams.get("documentId") ?? "").trim();
const q = String(searchParams.get("q") ?? "").trim().toLowerCase();
if (!documentId) {
return NextResponse.json({ error: "缺少 documentId" }, { status: 400 });
}
const { data: doc, error: docError } = await supabase
.from("documents")
.select("id,workspace_id,title")
.eq("id", documentId)
.eq("user_id", session.user.id)
.maybeSingle();
if (docError) {
return NextResponse.json({ error: docError.message }, { status: 400 });
}
if (!doc) {
return NextResponse.json({ error: "页面不存在" }, { status: 404 });
}
const { data: mediaRows } = await supabase
.from("media_assets")
.select("id,asset_type,file_url,file_name,mime_type,document_id,workspace_id,deleted_at")
.eq("document_id", documentId)
.eq("workspace_id", doc.workspace_id)
.is("deleted_at", null)
.order("created_at", { ascending: false })
.limit(200);
const mediaAssets = ((mediaRows ?? []) as MediaAsset[]).map((row) => ({
kind: "media" as const,
id: String(row.id),
title: String(row.file_name ?? row.id ?? "附件"),
fileUrl: String(row.file_url ?? ""),
mimeType: (row as any).mime_type ?? null,
assetType: (row as any).asset_type ?? null,
fileName: (row as any).file_name ?? null,
}));
const localMindmaps = (await detectLocalMindmapFiles([documentId]))
.filter((x) => x.documentId === documentId)
.map((x) => ({
kind: "local-mindmap" as const,
id: `mindmap:${x.mindmapId}`,
title: x.fileName,
fileUrl: `/documents/${documentId}/${x.fileName}`,
mimeType: "application/json",
assetType: "mindmap",
fileName: x.fileName,
}));
const testPdfs = await listTestPdfs();
let items: AgentAssetItem[] = [...localMindmaps, ...mediaAssets, ...testPdfs];
if (q) {
items = items.filter((it) => {
const hay = `${it.title} ${it.fileName ?? ""}`.toLowerCase();
return hay.includes(q);
});
}
return NextResponse.json({
ok: true,
workspaceId: doc.workspace_id,
documentId,
items,
});
}