diff --git a/components/script-renderer/ScriptRenderer.tsx b/components/script-renderer/ScriptRenderer.tsx index 5db2227..8c4b9c5 100644 --- a/components/script-renderer/ScriptRenderer.tsx +++ b/components/script-renderer/ScriptRenderer.tsx @@ -16,13 +16,32 @@ export const ScriptRenderer: React.FC = ({ data }) => { 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 contentEditableRef = useRef(null); + const [addThemeTag, setAddThemeTag] = useState([]); const [isInit, setIsInit] = useState(true); useEffect(() => { - setEditBlockId(null); - }, [activeBlockId]); + const themeBlock = data.blocks.find(block => block.type === 'theme'); + if (themeBlock) { + setAddThemeTag(themeBlock.content.map(item => item.text || '')); + } + }, [data.blocks]); + + // 添加聚焦效果 + useEffect(() => { + if (editBlockId && contentEditableRef.current) { + setTimeout(() => { + contentEditableRef.current?.focus(); + // 可选:将光标移到文本末尾 + const range = document.createRange(); + const sel = window.getSelection(); + range.selectNodeContents(contentEditableRef.current as Node); + range.collapse(false); + sel?.removeAllRanges(); + sel?.addRange(range); + }, 0); + } + }, [editBlockId]); const scrollToBlock = (blockId: string) => { const element = contentRefs.current[blockId]; @@ -32,14 +51,6 @@ export const ScriptRenderer: React.FC = ({ data }) => { } }; - // 使用 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) { @@ -93,6 +104,20 @@ export const ScriptRenderer: React.FC = ({ data }) => { setEditBlockId(null); }; + const handleThemeTagChange = (value: string[]) => { + console.log('主题标签更改', value); + if (value.length > 5) { + return toast.error('最多可选择5个主题标签'); + } + setAddThemeTag(value); + }; + + const handleEditBlock = (block: ScriptBlock) => { + setIsInit(false); + setEditBlockId(block.id); + setActiveBlockId(block.id); + }; + const renderEditBlock = (block: ScriptBlock) => { let blockHtmlText = ''; block.content.forEach(item => { @@ -119,13 +144,15 @@ export const ScriptRenderer: React.FC = ({ data }) => { case 'theme': return (
- {block.content.map((item, index) => ( + {addThemeTag.map((item, index) => (
- {item.text} - console.log(item.text)} /> + {item} + + handleThemeTagChange(addThemeTag.filter(v => v !== item)) + } />
))} - {/* 新增主题标签 */} + {/* 主题标签更改 */}
= ({ data }) => { options={Object.values(ThemeType).map(type => ({ label: type, value: type }))} value={addThemeTag} placeholder="Select Theme Type" - onChange={() => console.log('主题类型')} + onChange={(value) => { + console.log('主题标签更改', value); + handleThemeTagChange(value); + }} />
-
) @@ -157,9 +184,7 @@ export const ScriptRenderer: React.FC = ({ data }) => { { - setEditBlockId(block.id); - setActiveBlockId(block.id); - setIsInit(false); + handleEditBlock(block); }} /> = ({ data }) => { renderEditBlock(block) ) : ( block.content.map((item, index) => ( -
{renderContent(item)}
+
handleEditBlock(block)}>{renderContent(item)}
)) )} @@ -213,10 +238,10 @@ export const ScriptRenderer: React.FC = ({ data }) => { return (
-
+
{data.blocks.map(renderBlock)}
-
+
{/* 翻译功能 待开发 */} {/*

diff --git a/components/script-renderer/types.ts b/components/script-renderer/types.ts index ae01027..c340846 100644 --- a/components/script-renderer/types.ts +++ b/components/script-renderer/types.ts @@ -47,16 +47,16 @@ export enum ThemeTagBgColor { // 主题类型 enum export enum ThemeType { - satire = 'satire', // 讽刺 - absurdistComedy = 'absurdistComedy', // 荒诞喜剧 - disaster = 'disaster', // 灾难 - tragedy = 'tragedy', // 悲剧 - comedy = 'comedy', // 喜剧 - drama = 'drama', // 戏剧 - fantasy = 'fantasy', // 奇幻 - horror = 'horror', // 恐怖 - mystery = 'mystery', // 神秘 - romance = 'romance', // 爱情 - scienceFiction = 'scienceFiction', // 科幻 - thriller = 'thriller', // 惊悚 + satire = 'Satire', // 讽刺 + absurdistComedy = 'Absurdist Comedy', // 荒诞喜剧 + disaster = 'Disaster', // 灾难 + tragedy = 'Tragedy', // 悲剧 + comedy = 'Comedy', // 喜剧 + drama = 'Drama', // 戏剧 + fantasy = 'Fantasy', // 奇幻 + horror = 'Horror', // 恐怖 + mystery = 'Mystery', // 神秘 + romance = 'Romance', // 爱情 + scienceFiction = 'Science Fiction', // 科幻 + thriller = 'Thriller', // 惊悚 } \ No newline at end of file diff --git a/components/ui/select-dropdown.tsx b/components/ui/select-dropdown.tsx index 079d08f..f261536 100644 --- a/components/ui/select-dropdown.tsx +++ b/components/ui/select-dropdown.tsx @@ -12,9 +12,9 @@ interface SelectDropdownProps { dropdownId: string; label: string; options: SettingOption[]; - value: string; + value: string | Array; placeholder?: string; - onChange: (value: string) => void; + onChange: (value: string | Array) => void; } export const SelectDropdown = ( @@ -47,8 +47,12 @@ export const SelectDropdown = ( whileTap={{ scale: 0.99 }} >
- {options.find(opt => opt.value === value)?.label || value} - {placeholder && {placeholder}} + {Array.isArray(value) ? ( + {value.map(v => options.find(opt => opt.value === v)?.label).join(',')} + ) : ( + {options.find(opt => opt.value === value)?.label || value} + )} + {(!value || value.length === 0) && {placeholder}}
{ - onChange(option.value); + if (Array.isArray(value) && value.includes(option.value)) { + onChange(value.filter(v => v !== option.value)); + } else { + onChange(Array.isArray(value) ? [...value, option.value] : option.value); + } handleDropdownToggle(dropdownId); }} whileHover={{ x: 4 }} > {option.label} - {value === option.value && } + {value.includes(option.value) && } ))} diff --git a/components/workflow/work-office/common/TypewriterText.tsx b/components/workflow/work-office/common/TypewriterText.tsx index 0d922dc..406415a 100644 --- a/components/workflow/work-office/common/TypewriterText.tsx +++ b/components/workflow/work-office/common/TypewriterText.tsx @@ -35,15 +35,16 @@ export const TypewriterText: React.FC = ({ text, stableId } let currentIndex = 0; const typeNextChar = () => { + let addRandom = Math.floor(Math.random() * 10); if (currentIndex < text.length) { - const newText = text.slice(0, currentIndex + 1); + const newText = text.slice(0, currentIndex + addRandom); setDisplayState({ displayText: newText, isTyping: true, isComplete: false }); - currentIndex++; - animationRef.current = setTimeout(typeNextChar, 30); + currentIndex += addRandom; + animationRef.current = setTimeout(typeNextChar, 100); } else { setDisplayState({ displayText: text,