fix: AI 面板回复支持 Markdown 渲染
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dff9f90bf2
commit
bf66b269d4
1141
package-lock.json
generated
1141
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -60,6 +60,7 @@
|
|||||||
"pdfjs-dist": "^5.7.284",
|
"pdfjs-dist": "^5.7.284",
|
||||||
"react": "^19.2.5",
|
"react": "^19.2.5",
|
||||||
"react-dom": "^19.2.5",
|
"react-dom": "^19.2.5",
|
||||||
|
"react-markdown": "^10.1.0",
|
||||||
"tailwind-merge": "^3.5.0",
|
"tailwind-merge": "^3.5.0",
|
||||||
"zustand": "^5.0.12"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useState, useRef, useEffect, useCallback } from 'react'
|
import { useState, useRef, useEffect, useCallback } from 'react'
|
||||||
import { X, Send, Sparkles, Square, FileText, GripHorizontal } from 'lucide-react'
|
import { X, Send, Sparkles, Square, FileText, GripHorizontal } from 'lucide-react'
|
||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
import { useAppStore } from '../../stores/appStore'
|
import { useAppStore } from '../../stores/appStore'
|
||||||
import { streamAI } from '../../lib/ai'
|
import { streamAI } from '../../lib/ai'
|
||||||
import { extractTextFromJSON } from '../../lib/utils'
|
import { extractTextFromJSON } from '../../lib/utils'
|
||||||
@ -233,7 +234,7 @@ export function AiPanel() {
|
|||||||
{messages.map((msg, i) => (
|
{messages.map((msg, i) => (
|
||||||
<div key={i} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
<div key={i} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
||||||
<div
|
<div
|
||||||
className="max-w-[85%] rounded-2xl px-3 py-2 text-sm leading-relaxed whitespace-pre-wrap break-words"
|
className="max-w-[85%] rounded-2xl px-3 py-2 text-sm leading-relaxed break-words"
|
||||||
style={{
|
style={{
|
||||||
background: msg.role === 'user' ? 'var(--accent)' : 'var(--bg-muted)',
|
background: msg.role === 'user' ? 'var(--accent)' : 'var(--bg-muted)',
|
||||||
color: msg.role === 'user' ? '#fff' : 'var(--text)',
|
color: msg.role === 'user' ? '#fff' : 'var(--text)',
|
||||||
@ -241,7 +242,20 @@ export function AiPanel() {
|
|||||||
borderBottomLeftRadius: msg.role === 'assistant' ? 4 : undefined,
|
borderBottomLeftRadius: msg.role === 'assistant' ? 4 : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{msg.content}
|
{msg.role === 'assistant' ? (
|
||||||
|
<div className="prose prose-sm max-w-none">
|
||||||
|
<ReactMarkdown
|
||||||
|
components={{
|
||||||
|
p: ({children}) => <p className="mb-1 last:mb-0">{children}</p>,
|
||||||
|
ul: ({children}) => <ul className="list-disc pl-4 mb-1">{children}</ul>,
|
||||||
|
ol: ({children}) => <ol className="list-decimal pl-4 mb-1">{children}</ol>,
|
||||||
|
li: ({children}) => <li className="mb-0.5">{children}</li>,
|
||||||
|
code: ({children}) => <code className="px-1 rounded text-xs" style={{background:'var(--bg-muted)'}}>{children}</code>,
|
||||||
|
strong: ({children}) => <strong style={{color:'var(--text)'}}>{children}</strong>,
|
||||||
|
}}
|
||||||
|
>{msg.content}</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
) : msg.content}
|
||||||
{streaming && i === messages.length - 1 && msg.role === 'assistant' && (
|
{streaming && i === messages.length - 1 && msg.role === 'assistant' && (
|
||||||
<span className="ai-cursor" />
|
<span className="ai-cursor" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user