From 3c5f2f6fe13199dd12a1a4282eeb1b1ff1a0e209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=97=E6=9E=B3?= <7854742+wang_rumeng@user.noreply.gitee.com> Date: Wed, 20 Aug 2025 21:54:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=92=E8=89=B2=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E6=A1=86=E9=81=87=E5=88=B0=E7=89=B9=E6=AE=8A=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E6=8F=8F=E8=BF=B0=E5=AF=BC=E8=87=B4=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=B4=A9=E6=BA=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/service/adapter/textToShot.ts | 53 +++++++++++++++++++----------- components/ui/character-editor.tsx | 11 +++++-- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/app/service/adapter/textToShot.ts b/app/service/adapter/textToShot.ts index 6de8cf2..8a6ad2b 100644 --- a/app/service/adapter/textToShot.ts +++ b/app/service/adapter/textToShot.ts @@ -131,36 +131,45 @@ export class TextToShotAdapter { public static parseHighlight(text: string, tags: TagValueObject[]): ContentNode[] { const nodes: ContentNode[] = []; let currentText = text; - // 按内容长度降序排序,避免短名称匹配到长名称的一部分 - const sortedTags = [...tags].sort((a, b) => String(b.content).length - String(a.content).length); - - while (currentText.length > 0) { + + // 1. 确保 tags 是有效的数组 + if (!Array.isArray(tags)) { + console.warn('Invalid tags:', tags); + return [{ type: 'text', text: currentText }]; + } + + // 2. 恢复排序逻辑,并添加安全检查 + const sortedTags = [...tags] + .filter(tag => tag && tag.content) // 过滤无效的 tag + .sort((a, b) => String(b.content).length - String(a.content).length); + + // 3. 添加安全检查,防止无限循环 + let iterationCount = 0; + const MAX_ITERATIONS = 1000; // 设置一个合理的最大迭代次数 + + while (currentText.length > 0 && iterationCount < MAX_ITERATIONS) { + iterationCount++; let matchFound = false; - // 尝试匹配 for (const tag of sortedTags) { - if (currentText.startsWith(String(tag.content))) { - // 如果当前文本以tag内容开头 - if (currentText.length > String(tag.content).length) { - // 添加标记节点 + const tagContent = String(tag.content); + if (currentText.startsWith(tagContent)) { + if (currentText.length > tagContent.length) { nodes.push({ type: 'highlightText', attrs: { - text: String(tag.content), + text: tagContent, color: tag?.color || 'yellow' } }); - // 移除已处理的tag内容 - currentText = currentText.slice(String(tag.content).length); + currentText = currentText.slice(tagContent.length); matchFound = true; break; } } } - + if (!matchFound) { - // 如果没有找到tag匹配,处理普通文本 - // 查找下一个可能的tag内容位置 let nextTagIndex = currentText.length; for (const tag of sortedTags) { const index = currentText.indexOf(String(tag.content)); @@ -168,8 +177,7 @@ export class TextToShotAdapter { nextTagIndex = index; } } - - // 添加文本节点 + const textContent = currentText.slice(0, nextTagIndex); if (textContent) { nodes.push({ @@ -177,11 +185,18 @@ export class TextToShotAdapter { text: textContent }); } - // 移除已处理的文本 currentText = currentText.slice(nextTagIndex); } } - + + // 4. 如果达到最大迭代次数,处理剩余文本 + if (currentText.length > 0) { + nodes.push({ + type: 'text', + text: currentText + }); + } + return nodes; } private readonly ShotData: Shot; diff --git a/components/ui/character-editor.tsx b/components/ui/character-editor.tsx index 01b8fa9..08b10af 100644 --- a/components/ui/character-editor.tsx +++ b/components/ui/character-editor.tsx @@ -46,11 +46,18 @@ export const CharacterEditor = forwardRef(({ const paragraphs = TextToShotAdapter.fromTextToRole(description, highlight); console.log('-==========paragraphs===========-', paragraphs); setContent(paragraphs); - setTimeout(() => { + + // 保存定时器ID + const timerId = setTimeout(() => { setIsInit(false); setIsOptimizing(false); }, 100); - }, [highlight]); + + // 清理函数:组件卸载时清理定时器 + return () => { + clearTimeout(timerId); + }; + }, [description]); // 暴露方法给父组件 React.useImperativeHandle(ref, () => ({