♻️ 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
This commit is contained in:
Apple\Apple
2025-05-31 01:35:13 +08:00
parent caff73a746
commit 78353cb538

View File

@@ -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 autoCollapseState = applyAutoCollapseLogic(lastMessage, isThinkingComplete);
const shouldAutoCollapse = isThinkingComplete && !lastMessage.hasAutoCollapsed;
newMessage = { newMessage = {
...newMessage, ...newMessage,
content: newContent, content: newContent,
status: MESSAGE_STATUS.INCOMPLETE, status: MESSAGE_STATUS.INCOMPLETE,
isThinkingComplete: isThinkingComplete, ...autoCollapseState,
hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
isReasoningExpanded: shouldAutoCollapse
? false : lastMessage.isReasoningExpanded,
}; };
} }
@@ -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 autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
return [ return [
...prevMessage.slice(0, -1), ...prevMessage.slice(0, -1),
{ {
...lastMessage, ...lastMessage,
status: status, status: status,
isThinkingComplete: true, ...autoCollapseState,
hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
} }
]; ];
}); });
}, [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 autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
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, ...autoCollapseState,
hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
}; };
} }
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 autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
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, ...autoCollapseState,
hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
}; };
} }
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 autoCollapseState = applyAutoCollapseLogic(lastMessage, true);
const shouldAutoCollapse = !lastMessage.hasAutoCollapsed;
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, ...autoCollapseState,
hasAutoCollapsed: shouldAutoCollapse ? true : lastMessage.hasAutoCollapsed,
isReasoningExpanded: shouldAutoCollapse ? false : lastMessage.isReasoningExpanded
} }
]; ];
} }
return prevMessage; return prevMessage;
}); });
} }
}, [setMessage]); }, [setMessage, applyAutoCollapseLogic]);
// 发送请求 // 发送请求
const sendRequest = useCallback((payload, isStream) => { const sendRequest = useCallback((payload, isStream) => {