Commit ea632c6f by Apple\Apple

️ refactor(playground): eliminate code duplication in thinking content rendering

- Remove duplicate thinking content rendering logic from MessageContent component
- Import and utilize ThinkingContent component for consistent thinking display
- Clean up unused icon imports (ChevronRight, ChevronUp, Brain)
- Consolidate "思考中..." header text logic into single component
- Reduce code duplication by ~70 lines while maintaining all functionality
- Improve component separation of concerns and maintainability

The MessageContent component now delegates thinking content rendering to the
dedicated ThinkingContent component, eliminating the previously duplicated
UI logic and state management for thinking processes.
parent e30eca5c
...@@ -5,10 +5,8 @@ import { ...@@ -5,10 +5,8 @@ import {
Button, Button,
} from '@douyinfe/semi-ui'; } from '@douyinfe/semi-ui';
import MarkdownRenderer from '../common/markdown/MarkdownRenderer'; import MarkdownRenderer from '../common/markdown/MarkdownRenderer';
import ThinkingContent from './ThinkingContent';
import { import {
ChevronRight,
ChevronUp,
Brain,
Loader2, Loader2,
Check, Check,
X, X,
...@@ -127,7 +125,6 @@ const MessageContent = ({ ...@@ -127,7 +125,6 @@ const MessageContent = ({
currentDisplayableFinalContent = baseContentForDisplay.replace(/<\/?think>/g, '').trim(); currentDisplayableFinalContent = baseContentForDisplay.replace(/<\/?think>/g, '').trim();
} }
const headerText = (isThinkingStatus && !message.isThinkingComplete) ? t('思考中...') : t('思考过程');
const finalExtractedThinkingContent = currentExtractedThinkingContent; const finalExtractedThinkingContent = currentExtractedThinkingContent;
const finalDisplayableFinalContent = currentDisplayableFinalContent; const finalDisplayableFinalContent = currentDisplayableFinalContent;
...@@ -136,8 +133,8 @@ const MessageContent = ({ ...@@ -136,8 +133,8 @@ const MessageContent = ({
!finalExtractedThinkingContent && !finalExtractedThinkingContent &&
(!finalDisplayableFinalContent || finalDisplayableFinalContent.trim() === '')) { (!finalDisplayableFinalContent || finalDisplayableFinalContent.trim() === '')) {
return ( return (
<div className={`${className} flex items-center gap-2 sm:gap-4 bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl sm:rounded-2xl`}> <div className={`${className} flex items-center gap-2 sm:gap-4 bg-gradient-to-r from-purple-50 to-indigo-50`}>
<div className="w-4 h-4 rounded-full bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center shadow-lg"> <div className="w-5 h-5 rounded-full bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center shadow-lg">
<Loader2 className="animate-spin text-white" size={styleState.isMobile ? 16 : 20} /> <Loader2 className="animate-spin text-white" size={styleState.isMobile ? 16 : 20} />
</div> </div>
</div> </div>
...@@ -146,7 +143,6 @@ const MessageContent = ({ ...@@ -146,7 +143,6 @@ const MessageContent = ({
return ( return (
<div className={className}> <div className={className}>
{/* 为system角色添加特殊标识 */}
{message.role === 'system' && ( {message.role === 'system' && (
<div className="mb-2 sm:mb-4"> <div className="mb-2 sm:mb-4">
<div className="flex items-center gap-2 p-2 sm:p-3 bg-gradient-to-r from-amber-50 to-orange-50 rounded-lg" style={{ border: '1px solid var(--semi-color-border)' }}> <div className="flex items-center gap-2 p-2 sm:p-3 bg-gradient-to-r from-amber-50 to-orange-50 rounded-lg" style={{ border: '1px solid var(--semi-color-border)' }}>
...@@ -160,86 +156,17 @@ const MessageContent = ({ ...@@ -160,86 +156,17 @@ const MessageContent = ({
</div> </div>
)} )}
{/* 渲染推理内容 */} {message.role === 'assistant' && (
{message.role === 'assistant' && finalExtractedThinkingContent && ( <ThinkingContent
<div className="rounded-xl sm:rounded-2xl mb-2 sm:mb-4 overflow-hidden shadow-sm backdrop-blur-sm"> message={message}
<div finalExtractedThinkingContent={finalExtractedThinkingContent}
className="flex items-center justify-between p-3 sm:p-5 cursor-pointer hover:bg-gradient-to-r hover:from-white/20 hover:to-purple-50/30 transition-all" thinkingSource={thinkingSource}
style={{ styleState={styleState}
background: 'linear-gradient(135deg, #4c1d95 0%, #6d28d9 50%, #7c3aed 100%)', onToggleReasoningExpansion={onToggleReasoningExpansion}
position: 'relative'
}}
onClick={() => onToggleReasoningExpansion(message.id)}
>
<div className="absolute inset-0 overflow-hidden">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white opacity-5 rounded-full"></div>
<div className="absolute -bottom-8 -left-8 w-24 h-24 bg-white opacity-10 rounded-full"></div>
</div>
<div className="flex items-center gap-2 sm:gap-4 relative">
<div className="w-6 h-6 sm:w-8 sm:h-8 rounded-full bg-white/20 flex items-center justify-center shadow-lg">
<Brain style={{ color: 'white' }} size={styleState.isMobile ? 12 : 16} />
</div>
<div className="flex flex-col">
<Typography.Text strong style={{ color: 'white' }} className="text-sm sm:text-base">
{headerText}
</Typography.Text>
{thinkingSource && (
<Typography.Text style={{ color: 'white' }} className="text-xs mt-0.5 opacity-80 hidden sm:block">
来源: {thinkingSource}
</Typography.Text>
)}
</div>
</div>
<div className="flex items-center gap-2 sm:gap-3 relative">
{isThinkingStatus && !message.isThinkingComplete && (
<div className="flex items-center gap-1 sm:gap-2">
<Loader2 style={{ color: 'white' }} className="animate-spin" size={styleState.isMobile ? 14 : 18} />
<Typography.Text style={{ color: 'white' }} className="text-xs sm:text-sm font-medium opacity-90">
思考中
</Typography.Text>
</div>
)}
{(!isThinkingStatus || message.isThinkingComplete) && (
<div className="w-5 h-5 sm:w-6 sm:h-6 rounded-full bg-white/20 flex items-center justify-center">
{message.isReasoningExpanded ?
<ChevronUp size={styleState.isMobile ? 12 : 16} style={{ color: 'white' }} /> :
<ChevronRight size={styleState.isMobile ? 12 : 16} style={{ color: 'white' }} />
}
</div>
)}
</div>
</div>
<div
className={`transition-all duration-500 ease-out ${message.isReasoningExpanded ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
} overflow-hidden bg-gradient-to-br from-purple-50 via-indigo-50 to-violet-50`}
>
{message.isReasoningExpanded && (
<div className="p-3 sm:p-5 pt-2 sm:pt-4">
<div
className="bg-white/70 backdrop-blur-sm rounded-lg sm:rounded-xl p-2 shadow-inner overflow-x-auto overflow-y-auto thinking-content-scroll"
style={{
maxHeight: '200px',
minHeight: '100px',
scrollbarWidth: 'thin',
scrollbarColor: 'rgba(0, 0, 0, 0.3) transparent'
}}
>
<div className="prose prose-xs sm:prose-sm prose-purple max-w-none text-xs sm:text-sm">
<MarkdownRenderer
content={finalExtractedThinkingContent}
className=""
/> />
</div>
</div>
</div>
)}
</div>
</div>
)} )}
{/* 渲染消息内容 */}
{isEditing ? ( {isEditing ? (
/* 编辑模式 */
<div className="space-y-3"> <div className="space-y-3">
<TextArea <TextArea
value={editValue} value={editValue}
...@@ -278,7 +205,6 @@ const MessageContent = ({ ...@@ -278,7 +205,6 @@ const MessageContent = ({
</div> </div>
</div> </div>
) : ( ) : (
/* 正常显示模式 */
(() => { (() => {
if (Array.isArray(message.content)) { if (Array.isArray(message.content)) {
const textContent = message.content.find(item => item.type === 'text'); const textContent = message.content.find(item => item.type === 'text');
...@@ -286,7 +212,6 @@ const MessageContent = ({ ...@@ -286,7 +212,6 @@ const MessageContent = ({
return ( return (
<div> <div>
{/* 显示图片 */}
{imageContents.length > 0 && ( {imageContents.length > 0 && (
<div className="mb-3 space-y-2"> <div className="mb-3 space-y-2">
{imageContents.map((imgItem, index) => ( {imageContents.map((imgItem, index) => (
...@@ -312,7 +237,6 @@ const MessageContent = ({ ...@@ -312,7 +237,6 @@ const MessageContent = ({
</div> </div>
)} )}
{/* 显示文本内容 */}
{textContent && textContent.text && typeof textContent.text === 'string' && textContent.text.trim() !== '' && ( {textContent && textContent.text && typeof textContent.text === 'string' && textContent.text.trim() !== '' && (
<div className={`prose prose-xs sm:prose-sm prose-gray max-w-none overflow-x-auto text-xs sm:text-sm ${message.role === 'user' ? 'user-message' : ''}`}> <div className={`prose prose-xs sm:prose-sm prose-gray max-w-none overflow-x-auto text-xs sm:text-sm ${message.role === 'user' ? 'user-message' : ''}`}>
<MarkdownRenderer <MarkdownRenderer
......
import React from 'react'; import React from 'react';
import { Typography } from '@douyinfe/semi-ui'; import { Typography } from '@douyinfe/semi-ui';
import MarkdownRenderer from '../common/MarkdownRenderer'; import MarkdownRenderer from '../common/markdown/MarkdownRenderer';
import { ChevronRight, ChevronUp, Brain, Loader2 } from 'lucide-react'; import { ChevronRight, ChevronUp, Brain, Loader2 } from 'lucide-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
...@@ -21,7 +21,7 @@ const ThinkingContent = ({ ...@@ -21,7 +21,7 @@ const ThinkingContent = ({
return ( return (
<div className="rounded-xl sm:rounded-2xl mb-2 sm:mb-4 overflow-hidden shadow-sm backdrop-blur-sm"> <div className="rounded-xl sm:rounded-2xl mb-2 sm:mb-4 overflow-hidden shadow-sm backdrop-blur-sm">
<div <div
className="flex items-center justify-between p-3 sm:p-5 cursor-pointer hover:bg-gradient-to-r hover:from-white/20 hover:to-purple-50/30 transition-all" className="flex items-center justify-between p-3 cursor-pointer hover:bg-gradient-to-r hover:from-white/20 hover:to-purple-50/30 transition-all"
style={{ style={{
background: 'linear-gradient(135deg, #4c1d95 0%, #6d28d9 50%, #7c3aed 100%)', background: 'linear-gradient(135deg, #4c1d95 0%, #6d28d9 50%, #7c3aed 100%)',
position: 'relative' position: 'relative'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment