diff --git a/crawler-module/frontend/index.html b/crawler-module/frontend/index.html index 072a57e..4ab4b95 100644 --- a/crawler-module/frontend/index.html +++ b/crawler-module/frontend/index.html @@ -1,10 +1,10 @@ - + - + - frontend + 新闻爬虫系统
diff --git a/crawler-module/frontend/public/favicon.svg b/crawler-module/frontend/public/favicon.svg new file mode 100644 index 0000000..ac3f2f0 --- /dev/null +++ b/crawler-module/frontend/public/favicon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/crawler-module/frontend/src/pages/Tasks.tsx b/crawler-module/frontend/src/pages/Tasks.tsx index 9f8b785..b5faaec 100644 --- a/crawler-module/frontend/src/pages/Tasks.tsx +++ b/crawler-module/frontend/src/pages/Tasks.tsx @@ -17,6 +17,7 @@ export function Tasks() { const [logs, setLogs] = useState([]) const wsRef = useRef(null) const logsEndRef = useRef(null) + const taskCardRefs = useRef>(new Map()) useEffect(() => { loadTasks() @@ -30,6 +31,13 @@ export function Tasks() { useEffect(() => { if (expandedTask) { connectWebSocket(expandedTask) + // 滚动到任务卡片 + setTimeout(() => { + const cardElement = taskCardRefs.current.get(expandedTask) + if (cardElement) { + cardElement.scrollIntoView({ behavior: 'smooth', block: 'center' }) + } + }, 100) } return () => { if (wsRef.current) { @@ -40,10 +48,11 @@ export function Tasks() { }, [expandedTask]) useEffect(() => { - if (logsEndRef.current) { - logsEndRef.current.scrollIntoView({ behavior: 'smooth' }) + // 只在首次展开时滚动到日志区域,而不是每次日志更新都滚动 + if (logsEndRef.current && logs.length === 0) { + logsEndRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' }) } - }, [logs]) + }, [logs.length]) const loadTasks = async () => { try { @@ -157,6 +166,11 @@ const loadTasks = async () => { {tasks.map((task) => ( { + if (el) { + taskCardRefs.current.set(task.id, el as HTMLDivElement) + } + }} variants={itemVariants} className="glass-card rounded-2xl overflow-hidden" >