"use client"; import { useCallback, useEffect, useState } from "react"; import { useToast } from "@/components/Toast"; import { Button } from "@/components/ui/Button"; import { api } from "@/lib/api/client"; import type { TemplateResponse } from "@/lib/api/types"; import { buttonClass } from "@/lib/ui/variants"; interface TemplateFillerProps { // 可填入的目标输入字段名(如 brief / text);空 → 不渲染(无可填字段)。匹配/回写按此 name。 targetField: string | null; // 目标字段的中文展示名(如「需求」「原文」);缺省回退到 name。仅用于展示,不暴露英文 key。 targetLabel?: string | null; // 选定模板 → 把其 body 填进目标字段(纯前端,不改生成器后端)。 onFill: (field: string, body: string) => void; } // 「从模板填入」(F3,纯前端):进场懒加载模板库,选一个把 body 填进生成器的 brief/原文输入。 // 与生成器后端解耦——只读 /templates 并回写本地表单值。无模板/无目标字段则不渲染。 export function TemplateFiller({ targetField, targetLabel, onFill, }: TemplateFillerProps) { const toast = useToast(); const [templates, setTemplates] = useState(null); const [open, setOpen] = useState(false); const load = useCallback(async (): Promise => { try { const { data, error } = await api.GET("/templates", {}); if (error || !data) { toast("加载模板失败。", "error"); setTemplates([]); return; } setTemplates(data); } catch { toast("加载模板请求异常,请检查网络。", "error"); setTemplates([]); } }, [toast]); useEffect(() => { if (open && templates === null) void load(); }, [open, templates, load]); if (!targetField) return null; const field = targetField; const fieldLabel = targetLabel ?? targetField; if (!open) { return ( ); } return (
选一个模板填入「{fieldLabel}」
{templates === null ? (

加载中…

) : templates.length === 0 ? (

(暂无模板,去模板库新建。)

) : (
    {templates.map((t) => (
  • ))}
)}
); }