From c3acd724dc35b17b7cc5c615bf6ac4c1bdffaeb2 Mon Sep 17 00:00:00 2001 From: weed33834 Date: Sun, 9 Aug 2026 00:06:17 +0800 Subject: [PATCH] fix: preserve custom system prompt on template switch & render SVG preview in history --- frontend/src/lib/api.ts | 1 + frontend/src/pages/Generate.tsx | 21 ++++++++++------ frontend/src/pages/History.tsx | 43 ++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 1176420..42d158b 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -103,4 +103,5 @@ export const api = { listHistory: (limit = 50) => req(`/api/history?limit=${limit}`), clearHistory: () => req("/api/history", { method: "DELETE" }), deleteHistory: (id: number) => req(`/api/history/${id}`, { method: "DELETE" }), + getGenerationSvg: (id: number) => req<{ svg: string }>(`/api/history/${id}/svg`), }; diff --git a/frontend/src/pages/Generate.tsx b/frontend/src/pages/Generate.tsx index ea0e9ed..8ccbadf 100644 --- a/frontend/src/pages/Generate.tsx +++ b/frontend/src/pages/Generate.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState, useCallback } from "react"; import CodeMirror from "@uiw/react-codemirror"; import { python } from "@codemirror/lang-python"; import { vscodeDark } from "@uiw/codemirror-theme-vscode"; @@ -24,6 +24,7 @@ export default function GeneratePage() { const [showDiff, setShowDiff] = useState(false); const svgRef = useRef(null); const abortRef = useRef(null); + const userModifiedRef = useRef(false); // 追踪用户是否手动修改了 systemOverride useEffect(() => { return () => { @@ -49,17 +50,23 @@ export default function GeneratePage() { // 当用户选择模板,把 user_template 灌入编辑框 const tpl = useMemo(() => templates.find((t) => t.id === templateId) || null, [templates, templateId]); useEffect(() => { + // 切换模板时重置用户修改标记 + userModifiedRef.current = false; if (tpl?.user_template && !userPrompt) { setUserPrompt(tpl.user_template); } - if (tpl?.system_prompt) setSystemOverride(tpl.system_prompt); + // 仅在用户未手动修改时,才将 systemOverride 同步为模板默认值 + if (tpl?.system_prompt && !userModifiedRef.current) { + setSystemOverride(tpl.system_prompt); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [templateId]); - // 模板切换时刷新 systemOverride(当用户没自定义时跟模板走) - useEffect(() => { - if (tpl) setSystemOverride(tpl.system_prompt || ""); - }, [tpl]); + // 用户手动编辑 systemOverride 时标记为已修改 + const handleSystemOverrideChange = useCallback((value: string) => { + userModifiedRef.current = true; + setSystemOverride(value); + }, []); async function run() { if (!modelId) { @@ -219,7 +226,7 @@ export default function GeneratePage() { rows={5} className="w-full input font-mono text-xs mt-2" value={systemOverride} - onChange={(e) => setSystemOverride(e.target.value)} + onChange={(e) => handleSystemOverrideChange(e.target.value)} placeholder="留空则使用后端默认科研绘图约束;选择模板时默认填入模板的 system_prompt" /> )} diff --git a/frontend/src/pages/History.tsx b/frontend/src/pages/History.tsx index d134186..e0baa58 100644 --- a/frontend/src/pages/History.tsx +++ b/frontend/src/pages/History.tsx @@ -9,6 +9,9 @@ export default function HistoryPage() { const [items, setItems] = useState([]); const [active, setActive] = useState(null); const [msg, setMsg] = useState(""); + const [svgContent, setSvgContent] = useState(null); + const [svgLoading, setSvgLoading] = useState(false); + const [svgError, setSvgError] = useState(""); async function load() { try { @@ -21,16 +24,33 @@ export default function HistoryPage() { load(); }, []); + async function selectRecord(r: GenerationRecord) { + setActive(r); + setSvgContent(null); + setSvgError(""); + setSvgLoading(true); + try { + const result = await api.getGenerationSvg(r.id); + setSvgContent(result.svg || null); + } catch (e) { + setSvgError("SVG 加载失败:" + (e as Error).message); + } finally { + setSvgLoading(false); + } + } + async function clearAll() { if (!confirm("清空全部历史?")) return; await api.clearHistory(); setItems([]); setActive(null); + setSvgContent(null); } async function remove(id: number) { await api.deleteHistory(id); setActive(null); + setSvgContent(null); await load(); } @@ -52,7 +72,7 @@ export default function HistoryPage() { items.map((r) => (
  • setActive(r)} + onClick={() => selectRecord(r)} className={`p-3 border rounded cursor-pointer text-sm ${ active?.id === r.id ? "bg-slate-100 border-slate-400" : "hover:bg-slate-50" }`} @@ -104,6 +124,27 @@ export default function HistoryPage() { editable={false} /> +
    +
    +
    SVG 预览
    +
    + {svgError && ( +
    {svgError}
    + )} +
    + {svgLoading ? ( +
    SVG 加载中…
    + ) : svgContent ? ( +
    + ) : ( +
    暂无 SVG 内容
    + )} +
    +
    ) : (
    点击左侧查看详情。