feat: 添加 favicon.svg 文件并在 index.html 中引用
This commit is contained in:
parent
f470affb2f
commit
3f9bb22097
@ -4,6 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>PicoBot</title>
|
<title>PicoBot</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
3
web/public/favicon.svg
Normal file
3
web/public/favicon.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#22d3ee" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 247 B |
@ -15,6 +15,8 @@ export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps
|
|||||||
const prevShowBottomRef = useRef(false)
|
const prevShowBottomRef = useRef(false)
|
||||||
const prevShowTopRef = useRef(false)
|
const prevShowTopRef = useRef(false)
|
||||||
const lastMessageCountRef = useRef(0)
|
const lastMessageCountRef = useRef(0)
|
||||||
|
const prevMessageCountRef = useRef(0)
|
||||||
|
const stickyLockUntilRef = useRef(0)
|
||||||
const isProgrammaticScrollRef = useRef(false)
|
const isProgrammaticScrollRef = useRef(false)
|
||||||
const scrollTimerRef = useRef<number>(0)
|
const scrollTimerRef = useRef<number>(0)
|
||||||
|
|
||||||
@ -28,6 +30,12 @@ export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps
|
|||||||
const el = containerRef.current
|
const el = containerRef.current
|
||||||
if (!el) return
|
if (!el) return
|
||||||
|
|
||||||
|
// sticky lock 期间:防止中间 DOM 状态的 scroll 事件打断历史加载
|
||||||
|
if (Date.now() < stickyLockUntilRef.current) {
|
||||||
|
isStickyRef.current = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight
|
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight
|
||||||
const nearBottom = distanceFromBottom < 120
|
const nearBottom = distanceFromBottom < 120
|
||||||
|
|
||||||
@ -81,13 +89,31 @@ export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps
|
|||||||
// ---- auto-scroll effect ----
|
// ---- auto-scroll effect ----
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messages.length === 0) return
|
// 消息清空 → 重置所有追踪状态(话题/会话切换)
|
||||||
|
if (messages.length === 0) {
|
||||||
|
prevMessageCountRef.current = 0
|
||||||
|
lastMessageCountRef.current = 0
|
||||||
|
isStickyRef.current = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const lastMessage = messages[messages.length - 1]
|
const lastMessage = messages[messages.length - 1]
|
||||||
|
const isFreshLoad = prevMessageCountRef.current === 0 && messages.length > 0
|
||||||
|
|
||||||
// 用户自己发的消息 → 始终滚到底部
|
// 用户自己发的消息 → 始终滚到底部
|
||||||
if (lastMessage.role === 'user') {
|
if (lastMessage.role === 'user') {
|
||||||
scrollToBottom('instant')
|
scrollToBottom('instant')
|
||||||
|
prevMessageCountRef.current = messages.length
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新加载(话题切换后首次收到消息)→ 强制滚到底部
|
||||||
|
if (isFreshLoad) {
|
||||||
|
isStickyRef.current = true
|
||||||
|
lastMessageCountRef.current = 0
|
||||||
|
stickyLockUntilRef.current = Date.now() + 1500
|
||||||
|
scrollToBottom('instant')
|
||||||
|
prevMessageCountRef.current = messages.length
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +128,7 @@ export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastMessageCountRef.current = messages.length
|
lastMessageCountRef.current = messages.length
|
||||||
|
prevMessageCountRef.current = messages.length
|
||||||
}, [messages, scrollToBottom])
|
}, [messages, scrollToBottom])
|
||||||
|
|
||||||
// ---- ResizeObserver: 窗口大小变化时保持底部对齐 ----
|
// ---- ResizeObserver: 窗口大小变化时保持底部对齐 ----
|
||||||
@ -119,6 +146,15 @@ export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps
|
|||||||
return () => observer.disconnect()
|
return () => observer.disconnect()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// ---- 组件挂载时滚动到底部 ----
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (messages.length > 0) {
|
||||||
|
scrollToBottom('instant')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [])
|
||||||
|
|
||||||
// ---- 清理定时器 ----
|
// ---- 清理定时器 ----
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user