feat(playground): enhance SSE debugging and add image paste support with i18n

- Add SSEViewer component for interactive SSE message inspection
  * Display SSE data stream with collapsible panels
  * Show parsed JSON with syntax highlighting
  * Display key information badges (content, tokens, finish reason)
  * Support copy individual or all SSE messages
  * Show error messages with detailed information

- Support Ctrl+V to paste images in chat input
  * Enable image paste in CustomInputRender component
  * Auto-detect and add pasted images to image list
  * Show toast notifications for paste results

- Add complete i18n support for 6 languages
  * Chinese (zh): Complete translations
  * English (en): Complete translations
  * Japanese (ja): Add 28 new translations
  * French (fr): Add 28 new translations
  * Russian (ru): Add 28 new translations
  * Vietnamese (vi): Add 32 new translations

- Update .gitignore to exclude data directory
This commit is contained in:
ImogeneOctaviap794
2025-11-26 16:54:11 +08:00
parent a6a20a2069
commit 9140dee70c
20 changed files with 810 additions and 65 deletions

View File

@@ -59,6 +59,7 @@ import {
} from '../../components/playground/OptimizedComponents';
import ChatArea from '../../components/playground/ChatArea';
import FloatingButtons from '../../components/playground/FloatingButtons';
import { PlaygroundProvider } from '../../contexts/PlaygroundContext';
// 生成头像
const generateAvatarDataUrl = (username) => {
@@ -436,8 +437,26 @@ const Playground = () => {
setTimeout(() => saveMessagesImmediately([]), 0);
}, [setMessage, saveMessagesImmediately]);
// 处理粘贴图片
const handlePasteImage = useCallback((base64Data) => {
if (!inputs.imageEnabled) {
return;
}
// 添加图片到 imageUrls 数组
const newUrls = [...(inputs.imageUrls || []), base64Data];
handleInputChange('imageUrls', newUrls);
}, [inputs.imageEnabled, inputs.imageUrls, handleInputChange]);
// Playground Context 值
const playgroundContextValue = {
onPasteImage: handlePasteImage,
imageUrls: inputs.imageUrls || [],
imageEnabled: inputs.imageEnabled || false,
};
return (
<div className='h-full'>
<PlaygroundProvider value={playgroundContextValue}>
<div className='h-full'>
<Layout className='h-full bg-transparent flex flex-col md:flex-row'>
{(showSettings || !isMobile) && (
<Layout.Sider
@@ -536,6 +555,7 @@ const Playground = () => {
</Layout.Content>
</Layout>
</div>
</PlaygroundProvider>
);
};