185 lines
5.8 KiB
TypeScript
185 lines
5.8 KiB
TypeScript
import { eq } from "drizzle-orm";
|
|
import { type NextRequest, NextResponse } from "next/server";
|
|
import { auth } from "@/app/(auth)/auth";
|
|
import { readAgentPsdFonts } from "@/lib/agents/psd-font-settings";
|
|
import {
|
|
AGENT_PSD_TEMPLATE_CATEGORY_TAG_CONFIG_KEY,
|
|
defaultAgentPsdTemplateCategoryTagConfig,
|
|
normalizeAgentPsdTemplateCategoryTagConfig,
|
|
} from "@/lib/agents/psd-template-category-tag-config";
|
|
import {
|
|
type AgentPsdTemplate,
|
|
type AgentPsdTemplateListResponse,
|
|
getEditableAgentPsdTemplateLayers,
|
|
isAgentPsdTemplateReady,
|
|
isAgentPsdTemplateRuntimeReady,
|
|
isAgentPsdTextLayerSlot,
|
|
normalizeAgentPsdTemplateMode,
|
|
} from "@/lib/agents/psd-template-config";
|
|
import { repairAgentPsdTemplateFontBindings } from "@/lib/agents/psd-template-repair";
|
|
import {
|
|
AGENT_PSD_TEMPLATE_SECONDARY_CATEGORY_CONFIG_KEY,
|
|
defaultAgentPsdTemplateSecondaryCategoryConfig,
|
|
normalizeAgentPsdTemplateSecondaryCategoryConfig,
|
|
} from "@/lib/agents/psd-template-secondary-category-config";
|
|
import { readAgentPsdTemplates } from "@/lib/agents/psd-template-settings";
|
|
import {
|
|
AGENT_PSD_TEXT_COLOR_CONFIG_KEY,
|
|
defaultAgentPsdTextColorConfig,
|
|
normalizeAgentPsdTextColorConfig,
|
|
resolveAgentPsdTextColorConfigForBrand,
|
|
} from "@/lib/agents/psd-text-color-config";
|
|
import { db } from "@/lib/db";
|
|
import { systemSettings } from "@/lib/db/schema";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
function jsonError(status: number, error: string) {
|
|
const payload: AgentPsdTemplateListResponse = {
|
|
success: false,
|
|
templates: [],
|
|
error,
|
|
};
|
|
return NextResponse.json(payload, { status });
|
|
}
|
|
|
|
function toPublicTemplateSummary(template: AgentPsdTemplate): AgentPsdTemplate {
|
|
return {
|
|
...template,
|
|
layers: [],
|
|
};
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const session = await auth().catch(() => null);
|
|
if (!session?.user?.id) {
|
|
return jsonError(401, "未登录");
|
|
}
|
|
|
|
try {
|
|
const requestedBrand = String(
|
|
request.nextUrl.searchParams.get("brand") || ""
|
|
).trim();
|
|
const requestedModeRaw = String(
|
|
request.nextUrl.searchParams.get("mode") || ""
|
|
).trim();
|
|
const summaryOnly =
|
|
String(request.nextUrl.searchParams.get("summary") || "").trim() === "1";
|
|
const requestedMode =
|
|
requestedModeRaw === "main" || requestedModeRaw === "sku"
|
|
? normalizeAgentPsdTemplateMode(requestedModeRaw)
|
|
: null;
|
|
const [
|
|
allTemplates,
|
|
textColorSetting,
|
|
secondaryCategorySetting,
|
|
categoryTagSetting,
|
|
] = await Promise.all([
|
|
readAgentPsdTemplates(),
|
|
db
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(eq(systemSettings.key, AGENT_PSD_TEXT_COLOR_CONFIG_KEY))
|
|
.limit(1)
|
|
.then((rows) => rows[0])
|
|
.catch(() => null),
|
|
db
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(
|
|
eq(
|
|
systemSettings.key,
|
|
AGENT_PSD_TEMPLATE_SECONDARY_CATEGORY_CONFIG_KEY
|
|
)
|
|
)
|
|
.limit(1)
|
|
.then((rows) => rows[0])
|
|
.catch(() => null),
|
|
db
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(
|
|
eq(systemSettings.key, AGENT_PSD_TEMPLATE_CATEGORY_TAG_CONFIG_KEY)
|
|
)
|
|
.limit(1)
|
|
.then((rows) => rows[0])
|
|
.catch(() => null),
|
|
]);
|
|
let templates = allTemplates
|
|
.filter((template) => template.status === "active")
|
|
.filter(isAgentPsdTemplateReady)
|
|
.filter((template) =>
|
|
requestedBrand ? template.brandName === requestedBrand : true
|
|
)
|
|
.filter((template) =>
|
|
requestedMode ? template.mode === requestedMode : true
|
|
)
|
|
.filter(isAgentPsdTemplateRuntimeReady)
|
|
.filter(
|
|
(template) => getEditableAgentPsdTemplateLayers(template).length > 0
|
|
);
|
|
|
|
if (summaryOnly) {
|
|
templates = templates.map(toPublicTemplateSummary);
|
|
} else {
|
|
const fonts = (await readAgentPsdFonts().catch(
|
|
() => [] as Awaited<ReturnType<typeof readAgentPsdFonts>>
|
|
)) as Awaited<ReturnType<typeof readAgentPsdFonts>>;
|
|
const fontMap = new Map(fonts.map((font) => [font.id, font]));
|
|
templates = templates
|
|
.map((template) => repairAgentPsdTemplateFontBindings(template, fonts))
|
|
.map((template) => ({
|
|
...template,
|
|
layers: template.layers.map((layer) => {
|
|
if (!isAgentPsdTextLayerSlot(layer) || !layer.fontId) {
|
|
return layer;
|
|
}
|
|
|
|
const font = fontMap.get(layer.fontId);
|
|
if (!font) {
|
|
return layer;
|
|
}
|
|
|
|
return {
|
|
...layer,
|
|
fontFileUrl: font.fileUrl,
|
|
fontContentType: font.contentType,
|
|
};
|
|
}),
|
|
}));
|
|
}
|
|
|
|
const normalizedTextColorConfig = textColorSetting
|
|
? normalizeAgentPsdTextColorConfig(textColorSetting.value)
|
|
: defaultAgentPsdTextColorConfig;
|
|
|
|
const response = NextResponse.json({
|
|
success: true,
|
|
templates,
|
|
textColorConfig: requestedBrand
|
|
? resolveAgentPsdTextColorConfigForBrand(
|
|
normalizedTextColorConfig,
|
|
requestedBrand
|
|
)
|
|
: normalizedTextColorConfig,
|
|
secondaryCategoryConfig: secondaryCategorySetting
|
|
? normalizeAgentPsdTemplateSecondaryCategoryConfig(
|
|
secondaryCategorySetting.value
|
|
)
|
|
: defaultAgentPsdTemplateSecondaryCategoryConfig,
|
|
categoryTagConfig: categoryTagSetting
|
|
? normalizeAgentPsdTemplateCategoryTagConfig(categoryTagSetting.value)
|
|
: defaultAgentPsdTemplateCategoryTagConfig,
|
|
} satisfies AgentPsdTemplateListResponse);
|
|
response.headers.set(
|
|
"Cache-Control",
|
|
"private, no-store, max-age=0"
|
|
);
|
|
return response;
|
|
} catch (error) {
|
|
console.error("[PSD Templates] list failed:", error);
|
|
return jsonError(503, "PSD 模板读取失败");
|
|
}
|
|
}
|