From e6f987303617037c3102e121165c8173756894a5 Mon Sep 17 00:00:00 2001 From: admin <572701190@qq.com> Date: Sun, 3 May 2026 00:03:56 +0800 Subject: [PATCH] auto refresh workspace preview --- WebSite/src/App.tsx | 72 +++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/WebSite/src/App.tsx b/WebSite/src/App.tsx index ea15097..a79f59d 100644 --- a/WebSite/src/App.tsx +++ b/WebSite/src/App.tsx @@ -30,7 +30,6 @@ import { FolderOpen, Server, AlertCircle, - Eye, Info, X } from 'lucide-react'; @@ -464,27 +463,42 @@ export default function App() { showToast('密码更新成功'); }; - const handleUpdatePreview = async () => { - setIsPreviewLoading(true); - try { - const data = await apiRequest('/api/preview', { - method: 'POST', - body: JSON.stringify({ - inputDir: selectedInputDir, - angleDegrees: cervicalRotation - }) - }); - setPreviewImage(data.image); - setBackendOnline(true); - setBackendMessage('预览已由 head_extension_app.py 生成'); - showToast('预览已更新'); - } catch (error) { - setBackendOnline(false); - showToast((error as Error).message); - } finally { - setIsPreviewLoading(false); - } - }; + useEffect(() => { + if (currentPage !== 'workspace' || !selectedInputDir) return; + + const controller = new AbortController(); + const timer = window.setTimeout(async () => { + setIsPreviewLoading(true); + try { + const response = await fetch(`${API_BASE}/api/preview`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + inputDir: selectedInputDir, + angleDegrees: cervicalRotation + }), + signal: controller.signal + }); + const data = await response.json(); + if (!response.ok) throw new Error(data.error || '预览生成失败'); + setPreviewImage(data.image); + setBackendOnline(true); + setBackendMessage('预览已自动更新'); + } catch (error) { + if ((error as Error).name !== 'AbortError') { + setBackendOnline(false); + setBackendMessage((error as Error).message); + } + } finally { + if (!controller.signal.aborted) setIsPreviewLoading(false); + } + }, 300); + + return () => { + controller.abort(); + window.clearTimeout(timer); + }; + }, [currentPage, selectedInputDir, cervicalRotation]); const handleRunSimulation = async () => { if (isSimulating) return; @@ -694,11 +708,8 @@ export default function App() { -
- -
@@ -774,7 +785,10 @@ export default function App() {

快速 2D 预览

对应 head_extension_app.py 的 preview_deform_2d

- {cervicalRotation.toFixed(1)} DEG +
+ {cervicalRotation.toFixed(1)} DEG + {isPreviewLoading &&

自动更新中...

} +
{previewImage ? ( @@ -782,7 +796,7 @@ export default function App() { ) : (
-

点击“更新预览”读取影像库 DICOM

+

{isPreviewLoading ? '正在自动生成预览...' : '选择影像库数据后自动生成预览'}

)}