|
@@ -347,14 +347,23 @@ watch(
|
|
|
(v: string) => {
|
|
(v: string) => {
|
|
|
if (v === lastEmitted) return;
|
|
if (v === lastEmitted) return;
|
|
|
// 旧数据缩进存的是Quill class(ql-indent-N),先转成内联padding-left;
|
|
// 旧数据缩进存的是Quill class(ql-indent-N),先转成内联padding-left;
|
|
|
- // 再把手工敲的空格/Tab统一成不间断空格,保证不编辑直接保存也能在APP生效
|
|
|
|
|
- const next = stabilizeSpacesHtml(migrateIndentHtml(v || ''));
|
|
|
|
|
|
|
+ // 再把手工敲的空格/Tab统一成不间断空格,保证不编辑直接保存也能在APP生效。
|
|
|
|
|
+ // 转换在watch渲染期同步执行,一旦对畸形/超大内容抛错会连累整个Editor挂载失败、
|
|
|
|
|
+ // 弹窗打不开(表现为点"修改"没反应),所以异常时降级为原始内容,绝不阻断渲染
|
|
|
|
|
+ let next: string;
|
|
|
|
|
+ try {
|
|
|
|
|
+ next = stabilizeSpacesHtml(migrateIndentHtml(v || ''));
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('[Editor] 内容转换失败,降级为原始内容:', e);
|
|
|
|
|
+ next = v || '';
|
|
|
|
|
+ }
|
|
|
if (next !== content.value) {
|
|
if (next !== content.value) {
|
|
|
content.value = next || '<p></p>';
|
|
content.value = next || '<p></p>';
|
|
|
- // 转换结果同步回父组件表单,避免未编辑直接保存时丢掉空格缩进
|
|
|
|
|
|
|
+ // 转换结果同步回父组件表单,避免未编辑直接保存时丢掉空格缩进;
|
|
|
|
|
+ // 延迟到nextTick再发:setup/首帧渲染阶段同步emit改父表单,可能和弹窗首次渲染打架
|
|
|
if (next) {
|
|
if (next) {
|
|
|
lastEmitted = next;
|
|
lastEmitted = next;
|
|
|
- emit('update:modelValue', next);
|
|
|
|
|
|
|
+ nextTick(() => emit('update:modelValue', next));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
@@ -547,7 +556,13 @@ function stabilizeSpacesHtml(html: string): string {
|
|
|
|
|
|
|
|
// 内容变化统一出口:先做"空格缩进APP化"转换再发给父组件
|
|
// 内容变化统一出口:先做"空格缩进APP化"转换再发给父组件
|
|
|
function handleTextChange() {
|
|
function handleTextChange() {
|
|
|
- lastEmitted = stabilizeSpacesHtml(content.value);
|
|
|
|
|
|
|
+ // 同watch:转换抛错时降级为原始内容,保证编辑/保存链路不因转换异常中断
|
|
|
|
|
+ try {
|
|
|
|
|
+ lastEmitted = stabilizeSpacesHtml(content.value);
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('[Editor] 内容转换失败,降级为原始内容:', e);
|
|
|
|
|
+ lastEmitted = content.value;
|
|
|
|
|
+ }
|
|
|
emit('update:modelValue', lastEmitted);
|
|
emit('update:modelValue', lastEmitted);
|
|
|
}
|
|
}
|
|
|
|
|
|