From 9362b2559353d264ee2cdb7fdcbffb820fd477f9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 3 Apr 2026 19:50:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=AF=E6=8C=81=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E9=98=9F=E5=88=97=E6=89=B9=E9=87=8F=E4=B8=8A=E4=BC=A0PSD?= =?UTF-8?q?=E5=AD=97=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../psd-templates-settings-client.tsx | 99 ++++++++++++++++++- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/app/(admin)/settings/agent-workflow/psd-templates/psd-templates-settings-client.tsx b/app/(admin)/settings/agent-workflow/psd-templates/psd-templates-settings-client.tsx index d6bfe6677..9d48e13e6 100644 --- a/app/(admin)/settings/agent-workflow/psd-templates/psd-templates-settings-client.tsx +++ b/app/(admin)/settings/agent-workflow/psd-templates/psd-templates-settings-client.tsx @@ -1,7 +1,7 @@ "use client"; import Link from "next/link"; -import { useEffect, useMemo, useState, type ChangeEvent } from "react"; +import { useEffect, useMemo, useRef, useState, type ChangeEvent } from "react"; import useSWR from "swr"; import { toast } from "sonner"; import { @@ -104,6 +104,26 @@ function normalizeManagedBrandName(value?: string | null) { return normalized; } +function getQueuedFontFileKey(file: File) { + return [file.name, file.size, file.lastModified].join("__"); +} + +function mergeQueuedFontFiles(current: File[], incoming: File[]) { + const merged = [...current]; + const seen = new Set(current.map((file) => getQueuedFontFileKey(file))); + + for (const file of incoming) { + const key = getQueuedFontFileKey(file); + if (seen.has(key)) { + continue; + } + seen.add(key); + merged.push(file); + } + + return merged; +} + function hasTemplateCategoryTag(tags: string[] | undefined, target: string) { const normalizedTarget = String(target || "").trim().toLowerCase(); if (!normalizedTarget) { @@ -258,6 +278,7 @@ export function PsdTemplatesSettingsClient({ const [fontFamily, setFontFamily] = useState(""); const [fontUploadBrandName, setFontUploadBrandName] = useState(""); const [fontUploadFiles, setFontUploadFiles] = useState([]); + const fontFileInputRef = useRef(null); const [isCreating, setIsCreating] = useState(false); const [isCreatingAndParsing, setIsCreatingAndParsing] = useState(false); const [templateUploadPercent, setTemplateUploadPercent] = useState(0); @@ -487,9 +508,13 @@ export function PsdTemplatesSettingsClient({ function handleFontFileChange(event: ChangeEvent) { const nextFiles = Array.from(event.target.files || []); - setFontUploadFiles(nextFiles); + if (nextFiles.length === 0) { + return; + } - if (nextFiles.length === 1) { + setFontUploadFiles((current) => mergeQueuedFontFiles(current, nextFiles)); + + if (fontUploadFiles.length === 0 && nextFiles.length === 1) { const normalizedName = nextFiles[0]?.name.replace(/\.[^.]+$/, "") || ""; if (normalizedName && !fontUploadName.trim()) { setFontUploadName(normalizedName); @@ -498,6 +523,23 @@ export function PsdTemplatesSettingsClient({ setFontFamily(normalizedName); } } + + event.currentTarget.value = ""; + } + + function handleRemoveQueuedFontFile(file: File) { + setFontUploadFiles((current) => + current.filter( + (item) => getQueuedFontFileKey(item) !== getQueuedFontFileKey(file) + ) + ); + } + + function handleClearQueuedFontFiles() { + setFontUploadFiles([]); + if (fontFileInputRef.current) { + fontFileInputRef.current.value = ""; + } } async function saveCategoryTagConfig(nextTags: string[]) { @@ -734,6 +776,9 @@ export function PsdTemplatesSettingsClient({ setFontFamily(""); setFontUploadBrandName(""); setFontUploadFiles([]); + if (fontFileInputRef.current) { + fontFileInputRef.current.value = ""; + } await mutateFonts(); } catch (error) { toast.error(error instanceof Error ? error.message : "字体上传失败"); @@ -1435,11 +1480,15 @@ export function PsdTemplatesSettingsClient({
{ + event.currentTarget.value = ""; + }} />

{fontUploadFiles.length > 0 @@ -1448,13 +1497,55 @@ export function PsdTemplatesSettingsClient({ : `已选择 ${fontUploadFiles.length} 个字体文件:${fontUploadFiles .map((file) => file.name) .join("、")}` - : "支持一次选择多个字体文件批量上传,建议按实际字重分别整理后再导入"} + : "支持一次多选,也支持多次继续添加字体文件后再批量上传"}

{fontUploadFiles.length > 1 ? "批量上传时会使用每个文件名作为字体名称;如果填写了 CSS 字体族,会批量应用到这一批字体。" : "单个上传时可自定义字体名称和 CSS 字体族。"}

+ {fontUploadFiles.length > 0 ? ( +
+
+
+ 待上传文件队列 +
+ +
+
+ {fontUploadFiles.map((file) => ( +
+
+
{file.name}
+
+ {(file.size / 1024 / 1024).toFixed(2)} MB +
+
+ +
+ ))} +
+
+ ) : null}