Browse Source

♻️ refactor(playground): Refactor auto-collapse logic to eliminate code duplication

- Extract common `applyAutoCollapseLogic` function for reasoning panel collapse behavior
- Consolidate duplicated auto-collapse logic across multiple functions
- Simplify conditional expressions using logical OR operator
- Replace repetitive property assignments with object spread syntax
- Update dependency arrays to include new shared function
- Ensure consistent behavior across stream/non-stream/error scenarios

This refactoring improves code maintainability by following DRY principles
and centralizing the auto-collapse logic in a single reusable function.
All message handling functions now use consistent logic for determining
when to auto-collapse the reasoning panel.

Benefits:
- Reduced code duplication from ~20 lines to 6 lines per function
- Single source of truth for auto-collapse behavior
- Improved readability and maintainability
- Easier to modify collapse logic in the future

Files changed:
- web/src/hooks/useApiRequest.js: Refactored message handling functions
Apple\Apple 9 tháng trước cách đây
mục cha
commit
78353cb538
1 tập tin đã thay đổi với 25 bổ sung31 xóa
  1. 25 31
      web/src/hooks/useApiRequest.js

+ 25 - 31
web/src/hooks/useApiRequest.js

@@ -24,6 +24,16 @@ export const useApiRequest = (
 ) => {
 ) => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
+  // 处理消息自动关闭逻辑的公共函数
+  const applyAutoCollapseLogic = useCallback((message, isThinkingComplete = true) => {
+    const shouldAutoCollapse = isThinkingComplete && !message.hasAutoCollapsed;
+    return {
+      isThinkingComplete,
+      hasAutoCollapsed: shouldAutoCollapse || message.hasAutoCollapsed,
+      isReasoningExpanded: shouldAutoCollapse ? false : message.isReasoningExpanded,
+    };
+  }, []);
+
   // 流式消息更新
   // 流式消息更新
   const streamMessageUpdate = useCallback((textChunk, type) => {
   const streamMessageUpdate = useCallback((textChunk, type) => {
     setMessage(prevMessage => {
     setMessage(prevMessage => {
@@ -65,17 +75,13 @@ export const useApiRequest = (
           const isThinkingComplete = (lastMessage.reasoningContent && !lastMessage.isThinkingComplete) ||
           const isThinkingComplete = (lastMessage.reasoningContent && !lastMessage.isThinkingComplete) ||
             thinkingCompleteFromTags;
             thinkingCompleteFromTags;
 
 
-          // 只在第一次思考完成时自动关闭,之后由用户控制
-          const shouldAutoCollapse = isThinkingComplete && !lastMessage.hasAutoCollapsed;
+          const autoCollapseState = applyAutoCollapseLogic(lastMessage, isThinkingComplete);
 
 
           newMessage = {
           newMessage = {
             ...newMessage,
             ...newMessage,
             content: newContent,
             content: newContent,
             status: MESSAGE_STATUS.INCOMPLETE,
             status: MESSAGE_STATUS.INCOMPLETE,
-            isThinkingComplete: isThinkingComplete,
-            hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
-            isReasoningExpanded: shouldAutoCollapse
-              ? false : lastMessage.isReasoningExpanded,
+            ...autoCollapseState,
           };
           };
         }
         }
 
 
@@ -84,7 +90,7 @@ export const useApiRequest = (
 
 
       return prevMessage;
       return prevMessage;
     });
     });
-  }, [setMessage]);
+  }, [setMessage, applyAutoCollapseLogic]);
 
 
   // 完成消息
   // 完成消息
   const completeMessage = useCallback((status = MESSAGE_STATUS.COMPLETE) => {
   const completeMessage = useCallback((status = MESSAGE_STATUS.COMPLETE) => {
@@ -95,21 +101,18 @@ export const useApiRequest = (
         return prevMessage;
         return prevMessage;
       }
       }
 
 
-      // 只在第一次思考完成时自动关闭,之后由用户控制
-      const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
+      const autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
 
 
       return [
       return [
         ...prevMessage.slice(0, -1),
         ...prevMessage.slice(0, -1),
         {
         {
           ...lastMessage,
           ...lastMessage,
           status: status,
           status: status,
-          isThinkingComplete: true,
-          hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
-          isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
+          ...autoCollapseState,
         }
         }
       ];
       ];
     });
     });
-  }, [setMessage]);
+  }, [setMessage, applyAutoCollapseLogic]);
 
 
   // 非流式请求
   // 非流式请求
   const handleNonStreamRequest = useCallback(async (payload) => {
   const handleNonStreamRequest = useCallback(async (payload) => {
@@ -172,17 +175,14 @@ export const useApiRequest = (
           const newMessages = [...prevMessage];
           const newMessages = [...prevMessage];
           const lastMessage = newMessages[newMessages.length - 1];
           const lastMessage = newMessages[newMessages.length - 1];
           if (lastMessage?.status === MESSAGE_STATUS.LOADING) {
           if (lastMessage?.status === MESSAGE_STATUS.LOADING) {
-            // 只在第一次思考完成时自动关闭,之后由用户控制
-            const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
+            const autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
 
 
             newMessages[newMessages.length - 1] = {
             newMessages[newMessages.length - 1] = {
               ...lastMessage,
               ...lastMessage,
               content: processed.content,
               content: processed.content,
               reasoningContent: processed.reasoningContent,
               reasoningContent: processed.reasoningContent,
               status: MESSAGE_STATUS.COMPLETE,
               status: MESSAGE_STATUS.COMPLETE,
-              isThinkingComplete: true,
-              hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
-              isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
+              ...autoCollapseState,
             };
             };
           }
           }
           return newMessages;
           return newMessages;
@@ -202,22 +202,19 @@ export const useApiRequest = (
         const newMessages = [...prevMessage];
         const newMessages = [...prevMessage];
         const lastMessage = newMessages[newMessages.length - 1];
         const lastMessage = newMessages[newMessages.length - 1];
         if (lastMessage?.status === MESSAGE_STATUS.LOADING) {
         if (lastMessage?.status === MESSAGE_STATUS.LOADING) {
-          // 只在第一次思考完成时自动关闭,之后由用户控制
-          const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
+          const autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
 
 
           newMessages[newMessages.length - 1] = {
           newMessages[newMessages.length - 1] = {
             ...lastMessage,
             ...lastMessage,
             content: t('请求发生错误: ') + error.message,
             content: t('请求发生错误: ') + error.message,
             status: MESSAGE_STATUS.ERROR,
             status: MESSAGE_STATUS.ERROR,
-            isThinkingComplete: true,
-            hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
-            isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
+            ...autoCollapseState,
           };
           };
         }
         }
         return newMessages;
         return newMessages;
       });
       });
     }
     }
-  }, [setDebugData, setActiveDebugTab, setMessage, t]);
+  }, [setDebugData, setActiveDebugTab, setMessage, t, applyAutoCollapseLogic]);
 
 
   // SSE请求
   // SSE请求
   const handleSSE = useCallback((payload) => {
   const handleSSE = useCallback((payload) => {
@@ -337,7 +334,7 @@ export const useApiRequest = (
       streamMessageUpdate(t('建立连接时发生错误'), 'content');
       streamMessageUpdate(t('建立连接时发生错误'), 'content');
       completeMessage(MESSAGE_STATUS.ERROR);
       completeMessage(MESSAGE_STATUS.ERROR);
     }
     }
-  }, [setDebugData, setActiveDebugTab, streamMessageUpdate, completeMessage, t]);
+  }, [setDebugData, setActiveDebugTab, streamMessageUpdate, completeMessage, t, applyAutoCollapseLogic]);
 
 
   // 停止生成
   // 停止生成
   const onStopGenerator = useCallback(() => {
   const onStopGenerator = useCallback(() => {
@@ -355,8 +352,7 @@ export const useApiRequest = (
             lastMessage.reasoningContent || ''
             lastMessage.reasoningContent || ''
           );
           );
 
 
-          // 只在第一次思考完成时自动关闭,之后由用户控制
-          const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
+          const autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
 
 
           return [
           return [
             ...prevMessage.slice(0, -1),
             ...prevMessage.slice(0, -1),
@@ -365,16 +361,14 @@ export const useApiRequest = (
               status: MESSAGE_STATUS.COMPLETE,
               status: MESSAGE_STATUS.COMPLETE,
               reasoningContent: processed.reasoningContent || null,
               reasoningContent: processed.reasoningContent || null,
               content: processed.content,
               content: processed.content,
-              isThinkingComplete: true,
-              hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
-              isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
+              ...autoCollapseState,
             }
             }
           ];
           ];
         }
         }
         return prevMessage;
         return prevMessage;
       });
       });
     }
     }
-  }, [setMessage]);
+  }, [setMessage, applyAutoCollapseLogic]);
 
 
   // 发送请求
   // 发送请求
   const sendRequest = useCallback((payload, isStream) => {
   const sendRequest = useCallback((payload, isStream) => {