feat(ui): 添加 Markdown 渲染和代码高亮功能
- 新增 CodeBlock 组件,使用 Shiki 语法高亮 - 新增 Markdown 组件,支持 GFM 语法 - AI 消息自动渲染 Markdown,用户消息保持原样 - 代码块支持一键复制和语言标签显示
This commit is contained in:
@@ -7,6 +7,7 @@ import { motion } from 'framer-motion';
|
||||
import { useState } from 'react';
|
||||
import { cn } from '../utils/cn';
|
||||
import { fadeInUp, smoothTransition } from '../utils/animations';
|
||||
import { Markdown } from './Markdown';
|
||||
import type { Message } from '../api/client.js';
|
||||
|
||||
interface ChatMessageProps {
|
||||
@@ -43,7 +44,7 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
>
|
||||
{isUser ? <User size={18} /> : <Bot size={18} />}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex-1 min-w-0 overflow-hidden">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-sm text-gray-400">
|
||||
{isUser ? 'You' : 'AI Assistant'}
|
||||
@@ -56,8 +57,14 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
{copied ? <Check size={14} className="text-green-500" /> : <Copy size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
<div className="message-content whitespace-pre-wrap break-words">
|
||||
{message.content}
|
||||
<div className="message-content text-gray-200">
|
||||
{isUser ? (
|
||||
// 用户消息:保持原样显示
|
||||
<div className="whitespace-pre-wrap break-words">{message.content}</div>
|
||||
) : (
|
||||
// AI 消息:Markdown 渲染
|
||||
<Markdown content={message.content} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -79,14 +86,14 @@ export function StreamingMessage({ content }: StreamingMessageProps) {
|
||||
<div className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 bg-green-600">
|
||||
<Bot size={18} />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex-1 min-w-0 overflow-hidden">
|
||||
<div className="text-sm text-gray-400 mb-1">AI Assistant</div>
|
||||
<div className="message-content whitespace-pre-wrap break-words">
|
||||
{content}
|
||||
<div className="message-content text-gray-200">
|
||||
<Markdown content={content} />
|
||||
<motion.span
|
||||
animate={{ opacity: [1, 0] }}
|
||||
transition={{ duration: 0.8, repeat: Infinity, repeatType: 'reverse' }}
|
||||
className="inline-block w-2 h-4 bg-primary-400 ml-1 rounded-sm"
|
||||
className="inline-block w-2 h-4 bg-primary-400 ml-1 rounded-sm align-middle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user