From d2ecbec16ab9d7768b8d07a93d22816507d81833 Mon Sep 17 00:00:00 2001
From: hongjli <3117313295@qq.com>
Date: 星期日, 27 四月 2025 20:52:14 +0800
Subject: [PATCH] 渲染echarts图优化

---
 src/app/chat/page.tsx |   95 ++++++++++++++++++++++++++++-------------------
 1 files changed, 57 insertions(+), 38 deletions(-)

diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx
index e4d65cd..5530946 100644
--- a/src/app/chat/page.tsx
+++ b/src/app/chat/page.tsx
@@ -1,6 +1,6 @@
 'use client';
 
-import { useState, useEffect, useRef, useCallback } from 'react';
+import { useState, useEffect, useRef, useCallback, useContext, createContext } from 'react';
 import Link from 'next/link';
 import { useRouter } from 'next/navigation';
 import Image from 'next/image';
@@ -10,6 +10,9 @@
 import rehypeSanitize from 'rehype-sanitize';
 import dynamic from 'next/dynamic';
 import { ReactNode } from 'react';
+
+// 鍒涘缓涓�涓秷鎭畬鎴愮姸鎬佺殑Context
+const MessageCompletionContext = createContext<boolean>(true);
 
 // 鍔ㄦ�佸鍏� ECharts锛岀‘淇濆畠鍙湪瀹㈡埛绔覆鏌�
 const ReactECharts = dynamic(() => import('echarts-for-react'), { ssr: false });
@@ -272,27 +275,41 @@
 
 // 淇敼浠g爜鍧楁覆鏌撶粍浠讹紝娣诲姞鏇村ソ鐨勭被鍨嬫娴�
 function CodeBlockRenderer({ language, value }: { language: string; value: string }) {
-  // 鏇寸簿纭湴妫�娴婨Charts浠g爜
-  const isEchartsCode = () => {
+  // 鍒ゆ柇鏄惁鏄疛avaScript浠g爜锛屾娴嬫槸鍚﹀寘鍚浘琛ㄧ浉鍏崇壒寰�
+  const isEchartsCode = useCallback(() => {
     if (language !== 'javascript') return false;
     
     // 妫�鏌ユ槸鍚﹀寘鍚獷Charts鐗规湁鐨勯厤缃」
-    const hasEchartsConfig = 
-      value.includes('option =') || 
-      value.includes('const option') || 
-      value.includes('let option') || 
-      value.includes('series') &&
-      (value.includes('type:') || value.includes('tooltip:') || value.includes('xAxis:'));
-      
-    return hasEchartsConfig;
-  };
+    return value.includes('option') && 
+      (value.includes('series') || 
+       value.includes('chart') || 
+       value.includes('echarts') ||
+       value.includes('xAxis') ||
+       value.includes('yAxis'));
+  }, [language, value]);
   
-  // 濡傛灉鏄� ECharts 浠g爜鍒欐覆鏌撳浘琛�
-  if (isEchartsCode()) {
+  // 妫�鏌ユ秷鎭槸鍚﹀畬鏁� - 閫氳繃鐖剁粍浠朵紶閫掔殑isMessageComplete鐘舵��
+  const isComplete = useContext(MessageCompletionContext);
+  
+  // 鍦ㄦ秷鎭湭瀹屾垚鏃舵樉绀哄姞杞藉姩鐢�
+  if (language === 'javascript' && !isComplete) {
+    return (
+      <div className="w-full bg-gray-50 rounded-md my-4 p-6 text-center">
+        <div className="flex flex-col items-center justify-center">
+          <div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-gray-400 mb-4"></div>
+          <p className="text-gray-500">浠g爜鍔犺浇涓�...</p>
+          <p className="text-xs text-gray-400 mt-2">绛夊緟娑堟伅瀹屾垚鍚庡皢娓叉煋鍥捐〃</p>
+        </div>
+      </div>
+    );
+  }
+  
+  // 娑堟伅瀹屾垚鍚庯紝濡傛灉鏄浘琛ㄤ唬鐮佸垯娓叉煋涓哄浘琛�
+  if (isEchartsCode() && isComplete) {
     return <EchartsRenderer code={value} />;
   }
   
-  // 鍚﹀垯鎸夋櫘閫氫唬鐮佸潡娓叉煋
+  // 鏅�欽avaScript浠g爜鎴栧叾浠栬瑷�鐨勪唬鐮佸潡锛岀洿鎺ユ樉绀轰唬鐮�
   return (
     <div className="bg-gray-800 rounded-md my-2 overflow-hidden">
       <div className="flex items-center justify-between px-4 py-2 border-b border-gray-700">
@@ -1004,30 +1021,32 @@
                                 <div className="p-3">
                                   <div className="text-gray-800 leading-relaxed">
                                     {mainContent ? (
-                                      <ReactMarkdown
-                                        remarkPlugins={[remarkGfm]}
-                                        rehypePlugins={[rehypeRaw, rehypeSanitize]}
-                                        components={{
-                                          // @ts-ignore - ReactMarkdown 缁勪欢绫诲瀷瀹氫箟鐨勫吋瀹规�ч棶棰�
-                                          code: ({ node, inline, className, children, ...props }) => {
-                                            const match = /language-(\w+)/.exec(className || '');
-                                            const language = match ? match[1] : '';
-                                            const value = String(children).replace(/\n$/, '');
-                                            
-                                            if (!inline && match) {
-                                              return <CodeBlockRenderer language={language} value={value} />;
+                                      <MessageCompletionContext.Provider value={isMessageComplete && msg.id === currentMessageId}>
+                                        <ReactMarkdown
+                                          remarkPlugins={[remarkGfm]}
+                                          rehypePlugins={[rehypeRaw, rehypeSanitize]}
+                                          components={{
+                                            // @ts-ignore - ReactMarkdown 缁勪欢绫诲瀷瀹氫箟鐨勫吋瀹规�ч棶棰�
+                                            code: ({ node, inline, className, children, ...props }) => {
+                                              const match = /language-(\w+)/.exec(className || '');
+                                              const language = match ? match[1] : '';
+                                              const value = String(children).replace(/\n$/, '');
+                                              
+                                              if (!inline && match) {
+                                                return <CodeBlockRenderer language={language} value={value} />;
+                                              }
+                                              
+                                              return (
+                                                <code className={className} {...props}>
+                                                  {children}
+                                                </code>
+                                              );
                                             }
-                                            
-                                            return (
-                                              <code className={className} {...props}>
-                                                {children}
-                                              </code>
-                                            );
-                                          }
-                                        }}
-                                      >
-                                        {mainContent}
-                                      </ReactMarkdown>
+                                          }}
+                                        >
+                                          {mainContent}
+                                        </ReactMarkdown>
+                                      </MessageCompletionContext.Provider>
                                     ) : (
                                       msg.role === 'assistant' && !isMessageComplete ? '澶勭悊鍥炲涓�...' : ''
                                     )}

--
Gitblit v1.9.3