154 lines
4.8 KiB
TypeScript
154 lines
4.8 KiB
TypeScript
import { and, desc, eq, inArray, ne, sql } from "drizzle-orm";
|
|
import { NextResponse } from "next/server";
|
|
import { auth } from "@/app/(auth)/auth";
|
|
import { db } from "@/lib/db";
|
|
import { getSystemSetting } from "@/lib/db/queries";
|
|
import { mediaAsset } from "@/lib/db/schema";
|
|
import { createLogger } from "@/lib/observability/logger";
|
|
import {
|
|
VIDEO_CANVAS_FUNCTION_CONFIG_KEY,
|
|
defaultVideoCanvasFunctionConfig,
|
|
normalizeVideoCanvasFunctionConfig,
|
|
} from "@/lib/video-canvas/config";
|
|
import {
|
|
VIDEO_CANVAS_HISTORY_HIDDEN_AT_KEY,
|
|
VIDEO_CANVAS_HISTORY_MEDIA_TYPES,
|
|
normalizeVideoCanvasHistoryAssetIds,
|
|
} from "@/lib/video-canvas/history-assets";
|
|
import {
|
|
VIDEO_CANVAS_SUBJECT_UPLOAD_SOURCE_TYPE,
|
|
VIDEO_CANVAS_SUBJECT_VOICE_SOURCE_TYPE,
|
|
} from "@/lib/video-canvas/subjects";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const runtime = "nodejs";
|
|
|
|
const logger = createLogger("video-canvas-history-assets");
|
|
|
|
async function getHistoryConfig() {
|
|
const setting = await getSystemSetting({
|
|
key: VIDEO_CANVAS_FUNCTION_CONFIG_KEY,
|
|
}).catch(() => null);
|
|
return setting?.value
|
|
? normalizeVideoCanvasFunctionConfig(setting.value).historyAssets
|
|
: defaultVideoCanvasFunctionConfig.historyAssets;
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
const session = await auth();
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json(
|
|
{ success: false, error: "未登录" },
|
|
{ status: 401 },
|
|
);
|
|
}
|
|
|
|
const [config, assets] = await Promise.all([
|
|
getHistoryConfig(),
|
|
db
|
|
.select({
|
|
createdAt: mediaAsset.createdAt,
|
|
displayName: mediaAsset.displayName,
|
|
durationMs: mediaAsset.durationMs,
|
|
height: mediaAsset.height,
|
|
id: mediaAsset.id,
|
|
mediaType: mediaAsset.mediaType,
|
|
metadata: mediaAsset.metadata,
|
|
mimeType: mediaAsset.mimeType,
|
|
modelId: mediaAsset.modelId,
|
|
originalUrl: mediaAsset.originalUrl,
|
|
previewUrl: mediaAsset.previewUrl,
|
|
prompt: mediaAsset.prompt,
|
|
sourceNodeId: mediaAsset.sourceNodeId,
|
|
sourceType: mediaAsset.sourceType,
|
|
thumbnailUrl: mediaAsset.thumbnailUrl,
|
|
width: mediaAsset.width,
|
|
})
|
|
.from(mediaAsset)
|
|
.where(
|
|
and(
|
|
eq(mediaAsset.userId, session.user.id),
|
|
eq(mediaAsset.status, "ready"),
|
|
inArray(mediaAsset.mediaType, [
|
|
...VIDEO_CANVAS_HISTORY_MEDIA_TYPES,
|
|
]),
|
|
ne(
|
|
mediaAsset.sourceType,
|
|
VIDEO_CANVAS_SUBJECT_UPLOAD_SOURCE_TYPE,
|
|
),
|
|
ne(
|
|
mediaAsset.sourceType,
|
|
VIDEO_CANVAS_SUBJECT_VOICE_SOURCE_TYPE,
|
|
),
|
|
sql`coalesce(${mediaAsset.metadata}->>${VIDEO_CANVAS_HISTORY_HIDDEN_AT_KEY}, '') = ''`,
|
|
),
|
|
)
|
|
.orderBy(desc(mediaAsset.createdAt))
|
|
.limit(500),
|
|
]);
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
assets: config.enabled ? assets.slice(0, config.maxItems) : [],
|
|
});
|
|
} catch (error) {
|
|
logger.error("history asset list failed", { error });
|
|
return NextResponse.json(
|
|
{ success: false, error: "历史资产加载失败" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function DELETE(request: Request) {
|
|
try {
|
|
const session = await auth();
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json(
|
|
{ success: false, error: "未登录" },
|
|
{ status: 401 },
|
|
);
|
|
}
|
|
|
|
const body = (await request.json().catch(() => null)) as {
|
|
assetIds?: unknown;
|
|
} | null;
|
|
const assetIds = normalizeVideoCanvasHistoryAssetIds(body?.assetIds);
|
|
if (assetIds.length === 0) {
|
|
return NextResponse.json(
|
|
{ success: false, error: "请选择历史资产" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const hiddenAt = new Date().toISOString();
|
|
const hidden = await db
|
|
.update(mediaAsset)
|
|
.set({
|
|
metadata: sql`coalesce(${mediaAsset.metadata}, '{}'::jsonb) || ${JSON.stringify({
|
|
[VIDEO_CANVAS_HISTORY_HIDDEN_AT_KEY]: hiddenAt,
|
|
})}::jsonb`,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(
|
|
and(
|
|
eq(mediaAsset.userId, session.user.id),
|
|
eq(mediaAsset.status, "ready"),
|
|
inArray(mediaAsset.id, assetIds),
|
|
inArray(mediaAsset.mediaType, [...VIDEO_CANVAS_HISTORY_MEDIA_TYPES]),
|
|
sql`coalesce(${mediaAsset.metadata}->>${VIDEO_CANVAS_HISTORY_HIDDEN_AT_KEY}, '') = ''`,
|
|
),
|
|
)
|
|
.returning({ id: mediaAsset.id });
|
|
|
|
return NextResponse.json({ success: true, removed: hidden.length });
|
|
} catch (error) {
|
|
logger.error("history asset delete failed", { error });
|
|
return NextResponse.json(
|
|
{ success: false, error: "历史记录删除失败" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|