qwe
Some checks failed
Docker Build and Deploy / build-and-push (push) Has been cancelled
Docker Build and Deploy / deploy-hk (push) Has been cancelled

This commit is contained in:
zch1234qq
2025-10-21 09:17:52 +08:00
parent ecc8347146
commit 4afe6529fb
7 changed files with 1529 additions and 32 deletions

View File

@ -2,11 +2,11 @@ import React from 'react';
interface ChatMessageProps {
content: string;
sender: 'user' | 'bot';
role: 'user' | 'assistant';
timestamp: Date;
}
export const ChatMessage: React.FC<ChatMessageProps> = ({ content, sender, timestamp }) => {
export const ChatMessage: React.FC<ChatMessageProps> = ({ content, role, timestamp }) => {
// 格式化时间戳
const formattedTime = timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
@ -14,14 +14,14 @@ export const ChatMessage: React.FC<ChatMessageProps> = ({ content, sender, times
const messageParts = content.split('\n');
return (
<div className={`flex items-end mb-4 ${sender === 'user' ? 'justify-end' : 'justify-start'}`}>
{sender === 'bot' && (
<div className={`flex items-end mb-4 ${role === 'user' ? 'justify-end' : 'justify-start'}`}>
{role === 'assistant' && (
<div className="user-avatar mr-2">
<span>AI</span>
</div>
)}
<div className={`p-3 rounded-lg ${sender === 'user' ? 'message-user' : 'message-bot'}`}>
<div className={`p-3 rounded-lg ${role === 'user' ? 'message-user' : 'message-bot'}`}>
{messageParts.map((part, index) => (
<React.Fragment key={index}>
{part}
@ -30,7 +30,7 @@ export const ChatMessage: React.FC<ChatMessageProps> = ({ content, sender, times
))}
</div>
{sender === 'user' && (
{role === 'user' && (
<div className="user-avatar ml-2">
<span></span>
</div>

View File

@ -1,5 +1,10 @@
import React, { useRef } from 'react';
import { Box, Paper, Typography, Avatar, useMediaQuery, useTheme } from '@mui/material';
import ReactMarkdown from 'react-markdown';
// @ts-ignore // 临时忽略类型声明缺失,等待官方类型包或自定义声明
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
// @ts-ignore
import { dark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import type { Message as MessageType } from '../types/types';
interface MessageProps {
@ -8,7 +13,7 @@ interface MessageProps {
}
const Message: React.FC<MessageProps> = ({ message, isLast = false }) => {
const isUser = message.sender === 'user';
const isUser = message.role === 'user';
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const paperRef = useRef<HTMLDivElement>(null);
@ -67,14 +72,49 @@ const Message: React.FC<MessageProps> = ({ message, isLast = false }) => {
}
}}
>
<div style={{ lineHeight: 1.6 }}>
{message.content.split('\n').map((line, index) => (
<React.Fragment key={index}>
{line}
{index < message.content.split('\n').length - 1 && <br />}
</React.Fragment>
))}
</div>
<ReactMarkdown
components={{
//@ts-ignore // 临时忽略类型声明缺失,等待官方类型包或自定义声明
code({ inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighter
style={dark}
language={match[1]}
PreTag="div"
{...props}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
p: ({ ...props }) => <Typography variant="body1" paragraph sx={{ margin: '0.5em 0' }} {...props} />,
h1: ({ ...props }) => <Typography variant="h4" gutterBottom {...props} />,
h2: ({ ...props }) => <Typography variant="h5" gutterBottom {...props} />,
h3: ({ ...props }) => <Typography variant="h6" gutterBottom {...props} />,
ul: ({ ...props }) => <ul style={{ paddingLeft: '1.5em', margin: '0.5em 0' }} {...props} />,
ol: ({ ...props }) => <ol style={{ paddingLeft: '1.5em', margin: '0.5em 0' }} {...props} />,
li: ({ ...props }) => <li style={{ margin: '0.25em 0' }} {...props} />,
a: ({ ...props }) => <a style={{ color: theme.palette.primary.main, textDecoration: 'underline' }} {...props} />,
blockquote: ({ ...props }) => (
<blockquote style={{
borderLeft: `4px solid ${theme.palette.divider}`,
marginLeft: 0,
paddingLeft: '1em',
fontStyle: 'italic',
color: theme.palette.text.secondary
}} {...props} />
),
strong: ({ ...props }) => <strong style={{ fontWeight: 600 }} {...props} />,
em: ({ ...props }) => <em style={{ fontStyle: 'italic' }} {...props} />
}}
>
{message.content}
</ReactMarkdown>
<Typography
variant="caption"