0.1.13 AI功能大改
This commit is contained in:
@@ -7,10 +7,11 @@ export const dynamic = "force-dynamic";
|
||||
export async function GET(request: Request) {
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
data: { user },
|
||||
error: authError,
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (!session) {
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
@@ -47,10 +48,11 @@ export async function GET(request: Request) {
|
||||
export async function POST(request: Request) {
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
data: { user },
|
||||
error: authError,
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (!session) {
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
@@ -80,7 +82,7 @@ export async function POST(request: Request) {
|
||||
file_name: payload.fileName,
|
||||
file_size: payload.fileSize ?? null,
|
||||
mime_type: payload.mimeType ?? null,
|
||||
created_by: session.user.id,
|
||||
created_by: user.id,
|
||||
})
|
||||
.select("*")
|
||||
.single();
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
|
||||
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
|
||||
const backendUrl = process.env.BACKEND_URL ?? process.env.NEXT_PUBLIC_BACKEND_URL;
|
||||
if (backendUrl) {
|
||||
void fetch(`${backendUrl}/api/v1/tasks/media-ocr`, {
|
||||
method: "POST",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
const {
|
||||
data: { user },
|
||||
error: authError,
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(request.url);
|
||||
const assetId = searchParams.get("assetId");
|
||||
|
||||
if (!assetId) {
|
||||
return NextResponse.json({ error: "缺少 assetId" }, { status: 400 });
|
||||
}
|
||||
|
||||
// 获取资源信息
|
||||
const { data: asset, error: assetError } = await supabase
|
||||
.from("media_assets")
|
||||
.select("*")
|
||||
.eq("id", assetId)
|
||||
.single();
|
||||
|
||||
if (assetError || !asset) {
|
||||
return NextResponse.json({ error: "资源不存在" }, { status: 404 });
|
||||
}
|
||||
|
||||
// 对于图片,添加高质量参数以获得更好的显示效果
|
||||
// Supabase Storage 支持通过 URL 参数控制图片质量和尺寸
|
||||
const isImage = asset.mime_type?.startsWith("image/");
|
||||
let signedUrl: string;
|
||||
|
||||
if (isImage) {
|
||||
// 使用 createSignedUrl 并添加高质量参数
|
||||
// 注意:transform 参数需要在签名时指定
|
||||
const { data: signedUrlData, error: signError } = await supabase.storage
|
||||
.from(asset.bucket)
|
||||
.createSignedUrl(asset.storage_path, 60 * 60, {
|
||||
// 添加转换参数以获得高质量图片
|
||||
transform: {
|
||||
quality: 95, // 高质量
|
||||
format: "origin", // 保持原始格式
|
||||
},
|
||||
});
|
||||
|
||||
if (signError || !signedUrlData) {
|
||||
return NextResponse.json({ error: "生成签名 URL 失败" }, { status: 500 });
|
||||
}
|
||||
signedUrl = signedUrlData.signedUrl;
|
||||
} else {
|
||||
// 非图片文件,直接生成签名 URL
|
||||
const { data: signedUrlData, error: signError } = await supabase.storage
|
||||
.from(asset.bucket)
|
||||
.createSignedUrl(asset.storage_path, 60 * 60);
|
||||
|
||||
if (signError || !signedUrlData) {
|
||||
return NextResponse.json({ error: "生成签名 URL 失败" }, { status: 500 });
|
||||
}
|
||||
signedUrl = signedUrlData.signedUrl;
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
signedUrl,
|
||||
asset: {
|
||||
id: asset.id,
|
||||
file_name: asset.file_name,
|
||||
mime_type: asset.mime_type,
|
||||
file_size: asset.file_size,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -51,8 +51,20 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
// 为私有桶生成临时访问链接(7 天);前端可在需要时通过 /api/media/signed-url 刷新
|
||||
const { data: signed } = await supabase.storage.from(DOC_BUCKET).createSignedUrl(path, 60 * 60 * 24 * 7);
|
||||
const signedUrl = signed?.signedUrl ?? "";
|
||||
// 对于图片,使用高质量参数以获得更好的显示效果
|
||||
let signedUrl = "";
|
||||
if (assetType === "image") {
|
||||
const { data: signed } = await supabase.storage.from(DOC_BUCKET).createSignedUrl(path, 60 * 60 * 24 * 7, {
|
||||
transform: {
|
||||
quality: 95, // 高质量
|
||||
format: "origin", // 保持原始格式
|
||||
},
|
||||
});
|
||||
signedUrl = signed?.signedUrl ?? "";
|
||||
} else {
|
||||
const { data: signed } = await supabase.storage.from(DOC_BUCKET).createSignedUrl(path, 60 * 60 * 24 * 7);
|
||||
signedUrl = signed?.signedUrl ?? "";
|
||||
}
|
||||
|
||||
const { data: asset, error } = await supabase
|
||||
.from("media_assets")
|
||||
@@ -76,7 +88,11 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ asset: asset as MediaAsset });
|
||||
// 返回 asset 和一个特殊的 asset:id 格式用于存储在思维导图中
|
||||
return NextResponse.json({
|
||||
asset: asset as MediaAsset,
|
||||
mindmapUrl: `asset:${asset.id}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return NextResponse.json({ error: "上传失败" }, { status: 500 });
|
||||
|
||||
Reference in New Issue
Block a user