import React, { useRef, useState, useMemo, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { SquarePen, Lightbulb, Navigation, Globe, Copy, SendHorizontal, X, Plus } from 'lucide-react'; import { ScriptData, ScriptBlock, ScriptContent, ThemeTagBgColor, ThemeType } from './types'; import ContentEditable, { ContentEditableEvent } from 'react-contenteditable'; import { toast } from 'sonner'; import { SelectDropdown } from '@/components/ui/select-dropdown'; import { TypewriterText } from '@/components/workflow/work-office/common/TypewriterText'; interface ScriptRendererProps { data: ScriptData; } export const ScriptRenderer: React.FC = ({ data }) => { const [activeBlockId, setActiveBlockId] = useState(null); const [hoveredBlockId, setHoveredBlockId] = useState(null); const contentRefs = useRef<{ [key: string]: HTMLDivElement | null }>({}); const [editBlockId, setEditBlockId] = useState(null); const contentEditableRef = useRef(null); const [addThemeTag, setAddThemeTag] = useState(null); const [isInit, setIsInit] = useState(true); useEffect(() => { setEditBlockId(null); }, [activeBlockId]); const scrollToBlock = (blockId: string) => { const element = contentRefs.current[blockId]; if (element) { element.scrollIntoView({ behavior: 'smooth' }); setActiveBlockId(blockId); } }; // 使用 useMemo 缓存标签颜色映射 const randomThemeTagBgColor = useMemo(() => { return Object.values(ThemeTagBgColor).reduce((acc: Record, color: string) => { acc[color] = color; return acc; }, {}); }, []); // 用于渲染展示的 JSX const renderContent = (content: ScriptContent) => { switch (content.type) { case 'heading': return

{content.text}

; case 'bold': return {content.text}; case 'italic': return {content.text}; default: return

{ isInit ? ( ) : ( {content.text} ) }

; } }; // 用于生成编辑时的 HTML 字符串 const contentToHtml = (content: ScriptContent): string => { switch (content.type) { case 'heading': return `

${content.text}

`; case 'bold': return `${content.text}`; case 'italic': return `${content.text}`; default: return `

${content.text}

`; } }; // 格式化文本为 HTML const formatTextToHtml = (text: string) => { return text .split('\n') .map(line => line || '
') .join('
'); }; const handleBlockTextChange = (block: ScriptBlock) => (e: ContentEditableEvent) => { console.log(e.target.value); }; const handleBlockTextBlur = (block: ScriptBlock) => (e: ContentEditableEvent) => { console.log(e.target.value); setEditBlockId(null); }; const renderEditBlock = (block: ScriptBlock) => { let blockHtmlText = ''; block.content.forEach(item => { blockHtmlText += contentToHtml(item); }); return ( ); }; const renderTypeBlock = (block: ScriptBlock, isHovered: boolean, isActive: boolean, isEditing: boolean) => { switch (block.type) { case 'theme': return (
{block.content.map((item, index) => (
{item.text} console.log(item.text)} />
))} {/* 新增主题标签 */}
({ label: type, value: type }))} value={addThemeTag} placeholder="Select Theme Type" onChange={() => console.log('主题类型')} />
) default: return ( <> {(isHovered || isActive) && ( { setEditBlockId(block.id); setActiveBlockId(block.id); setIsInit(false); }} /> { navigator.clipboard.writeText(block.content.map(item => item.text).join('\n')); toast.success('Copied!'); }} /> )}
{isEditing ? ( renderEditBlock(block) ) : ( block.content.map((item, index) => (
{renderContent(item)}
)) )}
); } }; const renderBlock = (block: ScriptBlock) => { const isHovered = hoveredBlockId === block.id; const isActive = activeBlockId === block.id; const isEditing = editBlockId === block.id; return ( (contentRefs.current[block.id] = el)} onMouseEnter={() => setHoveredBlockId(block.id)} onMouseLeave={() => setHoveredBlockId(null)} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.3 }} >

{block.title}

{ renderTypeBlock(block, isHovered, isActive, isEditing) }
); }; return (
{data.blocks.map(renderBlock)}
{/* 翻译功能 待开发 */} {/*

翻译

*/}

导航

{data.blocks.map((block) => ( scrollToBlock(block.id)} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > {block.title} ))}
); };