| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import React, { useEffect, useRef } from 'react';
- import { Typography } from '@douyinfe/semi-ui';
- import MarkdownRenderer from '../common/markdown/MarkdownRenderer';
- import { ChevronRight, ChevronUp, Brain, Loader2 } from 'lucide-react';
- import { useTranslation } from 'react-i18next';
- const ThinkingContent = ({
- message,
- finalExtractedThinkingContent,
- thinkingSource,
- styleState,
- onToggleReasoningExpansion
- }) => {
- const { t } = useTranslation();
- const scrollRef = useRef(null);
- const lastContentRef = useRef('');
- const isThinkingStatus = message.status === 'loading' || message.status === 'incomplete';
- const headerText = (isThinkingStatus && !message.isThinkingComplete) ? t('思考中...') : t('思考过程');
- useEffect(() => {
- if (scrollRef.current && finalExtractedThinkingContent && message.isReasoningExpanded) {
- scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
- }
- }, [finalExtractedThinkingContent, message.isReasoningExpanded]);
- useEffect(() => {
- if (!isThinkingStatus) {
- lastContentRef.current = '';
- }
- }, [isThinkingStatus]);
- if (!finalExtractedThinkingContent) return null;
- let prevLength = 0;
- if (isThinkingStatus && lastContentRef.current) {
- if (finalExtractedThinkingContent.startsWith(lastContentRef.current)) {
- prevLength = lastContentRef.current.length;
- }
- }
- if (isThinkingStatus) {
- lastContentRef.current = finalExtractedThinkingContent;
- }
- return (
- <div className="rounded-xl sm:rounded-2xl mb-2 sm:mb-4 overflow-hidden shadow-sm backdrop-blur-sm">
- <div
- 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={{
- background: 'linear-gradient(135deg, #4c1d95 0%, #6d28d9 50%, #7c3aed 100%)',
- 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
- ref={scrollRef}
- 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',
- 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=""
- animated={isThinkingStatus}
- previousContentLength={prevLength}
- />
- </div>
- </div>
- </div>
- )}
- </div>
- </div>
- );
- };
- export default ThinkingContent;
|