|
@@ -1164,6 +1164,12 @@ const resetDisplayContent = () => {
|
|
|
imageRowRevealFinished.value = {};
|
|
imageRowRevealFinished.value = {};
|
|
|
imageRowRevealActive.value = {};
|
|
imageRowRevealActive.value = {};
|
|
|
hasVisibleAnswerContent.value = false;
|
|
hasVisibleAnswerContent.value = false;
|
|
|
|
|
+ // ⚠️ scope 退场补偿态也要清:`isScopeExitCompensating` 为真时**正文行是隐藏的**
|
|
|
|
|
+ // (见 shouldRenderTextContentRow),残留会让重写后的正文整段不显示
|
|
|
|
|
+ clearScopeExitTimer();
|
|
|
|
|
+ scopeExitHeight.value = 0;
|
|
|
|
|
+ scopeExitWidth.value = 0;
|
|
|
|
|
+ recordHeightLock.value = null;
|
|
|
count.value = 0;
|
|
count.value = 0;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -1535,6 +1541,25 @@ watch(
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * ⚠️ 内容**不是纯追加**时必须整体重置再全量解析。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 这里的增量解析只吃「比上次多出来的那一段」(`val.slice(count)`),
|
|
|
|
|
+ * 所以消息内容被**整块重写**(不是往后追加)时,切出来的会是新内容的**中段**——
|
|
|
|
|
+ * 那段中段会被当正文渲染出来(踩过:参考资料 JSON 的中段变成一坨文本显示在界面上)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 会整块重写的场景(F073 起):
|
|
|
|
|
+ * - 流式收尾的**卡片重排**(把政策卡片挪到正文之上)
|
|
|
|
|
+ * - `answer_end` 与增量拼接不一致时的整块重建
|
|
|
|
|
+ * - 撤草稿(内容被截短回基线)
|
|
|
|
|
+ * 纯追加(流式 delta / answer_end 的尾缀补齐)仍走增量路径,不重置、不闪。
|
|
|
|
|
+ */
|
|
|
|
|
+ if (!val.startsWith(originContent.value)) {
|
|
|
|
|
+ changeFlag++;
|
|
|
|
|
+ resetDisplayContent();
|
|
|
|
|
+ xmlFilter.reset(); // 解析器也是有状态的(buffer / 未闭合标签),一并清
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const diffText = val.slice(count.value);
|
|
const diffText = val.slice(count.value);
|
|
|
processRecordSections(diffText);
|
|
processRecordSections(diffText);
|
|
|
originContent.value = val;
|
|
originContent.value = val;
|