diff --git a/src/pages/chat/ChatPage.tsx b/src/pages/chat/ChatPage.tsx index 5acac87..bb02799 100644 --- a/src/pages/chat/ChatPage.tsx +++ b/src/pages/chat/ChatPage.tsx @@ -7,6 +7,7 @@ import ChatHeader from './components/ChatHeader'; import ChatBody from './components/ChatBody'; import ChatInput from './components/ChatInput'; import ChatDrawers from './components/ChatDrawers'; +import ChatOutline from './components/ChatOutline'; import { useChatScroll } from './hooks/useChatScroll'; import { useChatData } from './hooks/useChatData'; import { useChatSender } from './hooks/useChatSender'; @@ -97,21 +98,35 @@ export default function ChatPage() { onClear={sender.handleClear} /> - { - const content = mode === 'markdown' ? text : markdownToPlainText(text); - return navigator.clipboard?.writeText(content).then(() => message.success(mode === 'markdown' ? '已复制(Markdown)' : '已复制(纯文本)')); - }} - /> +
+ { + const content = mode === 'markdown' ? text : markdownToPlainText(text); + return navigator.clipboard + ?.writeText(content) + .then(() => message.success(mode === 'markdown' ? '已复制(Markdown)' : '已复制(纯文本)')); + }} + /> + + { + setHighlightId(msgId); + const el = document.getElementById('msg-' + msgId); + if (el) el.scrollIntoView({ block: 'start', behavior: 'smooth' }); + }} + /> +
s.trim()) + .filter(Boolean)[0]; + const text = (firstLine || plain.trim()).replace(/\s+/g, ' '); + if (text.length <= 44) return text; + return text.slice(0, 44) + '…'; +} + +export default function ChatOutline(props: { messages: ChatMessage[]; onJump: (id: string) => void; activeId?: string | null }) { + const { messages, onJump, activeId } = props; + const items = messages.filter((m) => m.role === 'assistant'); + + if (items.length === 0) return null; + + return ( + + ); +} + diff --git a/src/styles.css b/src/styles.css index 2155f59..9084f08 100644 --- a/src/styles.css +++ b/src/styles.css @@ -482,6 +482,12 @@ body { position: relative; } +.chat-content-row { + flex: 1; + min-height: 0; + display: flex; +} + .chat-header { height: 60px; padding: 0 24px; @@ -552,6 +558,73 @@ body { background: var(--color-bg); } +.chat-outline { + width: 260px; + border-left: 1px solid var(--color-border); + background: var(--color-surface); + padding: 14px 12px; + overflow: auto; +} + +.chat-outline-title { + font-size: 12px; + font-weight: 600; + color: var(--color-text-secondary); + margin-bottom: 10px; +} + +.chat-outline-list { + display: flex; + flex-direction: column; + gap: 6px; +} + +.chat-outline-item { + border: 1px solid var(--color-border); + background: var(--color-surface); + border-radius: 10px; + padding: 8px 10px; + text-align: left; + cursor: pointer; + display: flex; + gap: 8px; + align-items: flex-start; + color: var(--color-text); +} + +.chat-outline-item:hover { + border-color: var(--color-border-strong); + box-shadow: var(--shadow-xs); +} + +.chat-outline-item.active { + border-color: var(--color-brand); + box-shadow: var(--shadow-focus); +} + +.chat-outline-index { + font-size: 12px; + color: var(--color-text-tertiary); + line-height: 1.4; + flex: 0 0 auto; +} + +.chat-outline-text { + font-size: 12.5px; + line-height: 1.4; + color: var(--color-text); + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; +} + +@media (max-width: 1100px) { + .chat-outline { + display: none; + } +} + .chat-body .messages-container { max-width: 780px; width: 100%;