Your Name 11ab9a8e03
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: organize psd assets by brand and harden template editor
2026-04-02 18:29:41 +08:00

130 lines
3.6 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { upsertSystemSetting } from "@/lib/db/queries";
import { requireAgentWorkflowAdmin } from "@/lib/middleware/admin";
import {
AGENT_PSD_FONTS_KEY,
upsertAgentPsdFont,
type AgentPsdFontMutationResponse,
} from "@/lib/agents/psd-font-config";
import { isAgentPsdTextLayerSlot } from "@/lib/agents/psd-template-config";
import {
readAgentPsdFonts,
tryDeleteAgentPsdFontAssets,
} from "@/lib/agents/psd-font-settings";
import { readAgentPsdTemplates } from "@/lib/agents/psd-template-settings";
export const runtime = "nodejs";
const updateFontSchema = z.object({
name: z.string().trim().min(1).max(80),
family: z.string().trim().min(1).max(120),
brandName: z.string().trim().max(64).optional().nullable(),
});
function jsonError(status: number, error: string) {
const payload: AgentPsdFontMutationResponse = {
success: false,
error,
};
return NextResponse.json(payload, { status });
}
export async function PUT(
request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const session = await requireAgentWorkflowAdmin().catch(() => null);
if (!session?.user?.id) {
return jsonError(401, "未登录");
}
let body: z.infer<typeof updateFontSchema>;
try {
body = updateFontSchema.parse(await request.json());
} catch {
return jsonError(400, "字体参数不合法");
}
try {
const { id } = await context.params;
const fonts = await readAgentPsdFonts();
const currentFont = fonts.find((entry) => entry.id === id);
if (!currentFont) {
return jsonError(404, "字体不存在");
}
const updatedFont = {
...currentFont,
name: body.name.trim(),
family: body.family.trim(),
brandName: String(body.brandName || "").trim() || undefined,
updatedAt: new Date().toISOString(),
};
await upsertSystemSetting({
key: AGENT_PSD_FONTS_KEY,
value: upsertAgentPsdFont(fonts, updatedFont),
updatedBy: session.user.id,
});
return NextResponse.json({
success: true,
font: updatedFont,
} satisfies AgentPsdFontMutationResponse);
} catch (error) {
console.error("[PSD Fonts][Admin] update failed:", error);
return jsonError(502, "字体更新失败");
}
}
export async function DELETE(
request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const session = await requireAgentWorkflowAdmin().catch(() => null);
if (!session?.user?.id) {
return jsonError(401, "未登录");
}
try {
const { id } = await context.params;
const fonts = await readAgentPsdFonts();
const font = fonts.find((entry) => entry.id === id);
if (!font) {
return jsonError(404, "字体不存在");
}
const templates = await readAgentPsdTemplates();
const blockingTemplate = templates.find((template) =>
template.layers.some(
(layer) =>
isAgentPsdTextLayerSlot(layer) &&
layer.fontId === font.id &&
layer.isEditable
)
);
if (blockingTemplate) {
return jsonError(400, `字体仍被模板“${blockingTemplate.name}”使用,请先解除关联`);
}
await upsertSystemSetting({
key: AGENT_PSD_FONTS_KEY,
value: fonts.filter((entry) => entry.id !== id),
updatedBy: session.user.id,
});
await tryDeleteAgentPsdFontAssets(font);
return NextResponse.json({
success: true,
font,
} satisfies AgentPsdFontMutationResponse);
} catch (error) {
console.error("[PSD Fonts][Admin] delete failed:", error);
return jsonError(502, "字体删除失败");
}
}