fix: expose PSD parse action in upload panel
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-27 20:43:41 +08:00
parent bfbad743c4
commit ed7534a1ff

View File

@ -169,6 +169,7 @@ export function PsdTemplatesSettingsClient({
const [fontFamily, setFontFamily] = useState("");
const [fontUploadFile, setFontUploadFile] = useState<File | null>(null);
const [isCreating, setIsCreating] = useState(false);
const [isCreatingAndParsing, setIsCreatingAndParsing] = useState(false);
const [templateUploadPercent, setTemplateUploadPercent] = useState(0);
const [templateUploadStatus, setTemplateUploadStatus] = useState("");
const [isSaving, setIsSaving] = useState(false);
@ -289,7 +290,8 @@ export function PsdTemplatesSettingsClient({
}
}
async function handleCreateTemplate() {
async function handleCreateTemplate(options?: { parseAfterUpload?: boolean }) {
const parseAfterUpload = options?.parseAfterUpload === true;
if (!uploadFile) {
toast.error("请先选择 PSD / PSB 文件");
return;
@ -308,7 +310,8 @@ export function PsdTemplatesSettingsClient({
formData.set("file", uploadFile);
try {
setIsCreating(true);
setIsCreating(!parseAfterUpload);
setIsCreatingAndParsing(parseAfterUpload);
setTemplateUploadPercent(0);
setTemplateUploadStatus("上传中 0%");
@ -357,8 +360,14 @@ export function PsdTemplatesSettingsClient({
}
setTemplateUploadPercent(100);
setTemplateUploadStatus("上传完成,等待手动解析");
toast.success("PSD 文件已上传,请点击“解析 PSD”生成模板图层");
setTemplateUploadStatus(
parseAfterUpload ? "上传完成,正在提交 PSD 解析..." : "上传完成,等待手动解析"
);
toast.success(
parseAfterUpload
? "PSD 文件已上传,正在开始解析"
: "PSD 文件已上传,请点击“解析 PSD”生成模板图层"
);
setUploadName("");
setUploadBrandName("");
setUploadDescription("");
@ -366,12 +375,28 @@ export function PsdTemplatesSettingsClient({
await mutate();
setSelectedTemplateId(payload.template.id);
setDraftTemplate(cloneTemplate(payload.template));
if (parseAfterUpload) {
await handleParseTemplate(payload.template, {
skipCompletedConfirm: true,
onStart: () => {
setTemplateUploadStatus("正在解析 PSD,请稍候...");
},
onDone: () => {
setTemplateUploadStatus("解析完成");
},
onError: (message) => {
setTemplateUploadStatus(`解析失败:${message}`);
},
});
}
} catch (error) {
setTemplateUploadPercent(0);
setTemplateUploadStatus("");
toast.error(error instanceof Error ? error.message : "PSD 模板上传失败");
} finally {
setIsCreating(false);
setIsCreatingAndParsing(false);
}
}
@ -502,17 +527,26 @@ export function PsdTemplatesSettingsClient({
}
}
async function handleParseTemplate(template = selectedTemplate) {
async function handleParseTemplate(
template = selectedTemplate,
options?: {
skipCompletedConfirm?: boolean;
onStart?: () => void;
onDone?: () => void;
onError?: (message: string) => void;
}
) {
if (!template) return;
const actionLabel = template.parseStatus === "completed" ? "重新解析" : "解析";
const confirmed =
template.parseStatus === "completed"
template.parseStatus === "completed" && !options?.skipCompletedConfirm
? window.confirm(`确认重新解析模板“${template.name}”吗?`)
: true;
if (!confirmed) return;
try {
options?.onStart?.();
setParsingTemplateIds((current) =>
current.includes(template.id) ? current : [...current, template.id]
);
@ -566,9 +600,12 @@ export function PsdTemplatesSettingsClient({
setDraftTemplate(cloneTemplate(payload.template));
await mutate();
setSelectedTemplateId(payload.template.id);
options?.onDone?.();
} catch (error) {
await mutate();
toast.error(error instanceof Error ? error.message : "PSD 解析失败");
const message = error instanceof Error ? error.message : "PSD 解析失败";
options?.onError?.(message);
toast.error(message);
} finally {
setParsingTemplateIds((current) => current.filter((item) => item !== template.id));
}
@ -716,14 +753,37 @@ export function PsdTemplatesSettingsClient({
{uploadFile ? `已选择:${uploadFile.name}` : "支持 80MB 以内 PSD / PSB 文件"}
</p>
</div>
<Button onClick={handleCreateTemplate} disabled={isCreating} className="w-full">
{isCreating ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Upload className="mr-2 h-4 w-4" />
)}
上传模板文件
</Button>
<div className="grid gap-3 sm:grid-cols-2">
<Button
onClick={() => {
void handleCreateTemplate();
}}
disabled={isCreating || isCreatingAndParsing}
variant="outline"
className="w-full"
>
{isCreating ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Upload className="mr-2 h-4 w-4" />
)}
仅上传文件
</Button>
<Button
onClick={() => {
void handleCreateTemplate({ parseAfterUpload: true });
}}
disabled={isCreating || isCreatingAndParsing}
className="w-full bg-gradient-to-r from-orange-600 to-rose-600 hover:from-orange-500 hover:to-rose-500"
>
{isCreatingAndParsing ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Sparkles className="mr-2 h-4 w-4" />
)}
上传并解析
</Button>
</div>
{templateUploadStatus ? (
<div className="space-y-2 rounded-xl border border-dashed p-3">
<div className="flex items-center justify-between text-xs text-muted-foreground">