修复角色输入框遇到特殊角色描述导致页面崩溃问题

This commit is contained in:
北枳 2025-08-20 21:54:27 +08:00
parent 5c049fe964
commit 3c5f2f6fe1
2 changed files with 43 additions and 21 deletions

View File

@ -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;

View File

@ -46,11 +46,18 @@ export const CharacterEditor = forwardRef<any, CharacterEditorProps>(({
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, () => ({