|
@@ -182,41 +182,61 @@ export default {
|
|
|
},
|
|
|
watch: {
|
|
|
coms: {
|
|
|
- async handler(val) {
|
|
|
- // 如果正在保存,则跳过处理
|
|
|
- if (this.isSaving || !val) return;
|
|
|
+ handler(val) {
|
|
|
+
|
|
|
+ // 如果正在保存或没有值,则跳过处理
|
|
|
+ if (this.isSaving || !val || !Array.isArray(val)) return;
|
|
|
|
|
|
try {
|
|
|
+ // 检查是否需要更新
|
|
|
+ const needsUpdate = val.some((item, index) => {
|
|
|
+ const currentCom = this.comList[index];
|
|
|
+ if (!currentCom) return true;
|
|
|
+
|
|
|
+ // 比较关键属性是否发生变化
|
|
|
+ return (
|
|
|
+ item.content !== currentCom.content ||
|
|
|
+ item.dcb_nr !== currentCom.dcb_nr ||
|
|
|
+ JSON.stringify(item.attrs) !== JSON.stringify(currentCom.attrs) ||
|
|
|
+ JSON.stringify(item.dcb_attrs) !== JSON.stringify(currentCom.dcb_attrs)
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果不需要更新,直接返回
|
|
|
+ if (!needsUpdate) return;
|
|
|
+
|
|
|
// 处理拖拽数据,确保属性正确转换
|
|
|
const processedComs = val.map((item) => {
|
|
|
// 首先创建基础对象
|
|
|
- const processedItem = {
|
|
|
+ return {
|
|
|
...item,
|
|
|
- // 确保 attrs 是数组
|
|
|
- dcb_attrs: Array.isArray(item.attrs)
|
|
|
- ? item.attrs
|
|
|
- : JSON.parse(item.attrs || "[]"),
|
|
|
+ // 确保 attrs 和 dcb_attrs 都是数组
|
|
|
+ attrs: Array.isArray(item.attrs) ? item.attrs : [],
|
|
|
+ dcb_attrs: Array.isArray(item.dcb_attrs)
|
|
|
+ ? item.dcb_attrs
|
|
|
+ : (typeof item.dcb_attrs === 'string'
|
|
|
+ ? JSON.parse(item.dcb_attrs || '[]')
|
|
|
+ : []),
|
|
|
// 同步最新内容,优先使用当前显示的内容
|
|
|
- content: item.content || item.dcb_nr || "",
|
|
|
- dcb_nr: item.content || item.dcb_nr || "",
|
|
|
+ content: item.content || item.dcb_nr || '',
|
|
|
+ dcb_nr: item.content || item.dcb_nr || '',
|
|
|
// 确保 type 使用 dcb_type
|
|
|
type: item.dcb_type || item.type,
|
|
|
// 确保 name 使用 dcb_name
|
|
|
name: item.dcb_name || item.name,
|
|
|
};
|
|
|
-
|
|
|
- // 确保 content 和 dcb_nr 同步
|
|
|
- if (processedItem.content !== processedItem.dcb_nr) {
|
|
|
- processedItem.dcb_nr = processedItem.content;
|
|
|
- }
|
|
|
-
|
|
|
- return processedItem;
|
|
|
});
|
|
|
- console.log("editor_coms:",processedComs);
|
|
|
- this.comList = processedComs;
|
|
|
- this.$emit("onSetComs:", this.comList);
|
|
|
+
|
|
|
+ // 使用 Vue.set 更新整个数组
|
|
|
+ this.$set(this, 'comList', processedComs);
|
|
|
+ // 仅在数据确实发生变化时才触发父组件更新
|
|
|
+ this.$emit("onSetComs", this.comList);
|
|
|
} catch (error) {
|
|
|
console.error('处理组件数据时出错:', error);
|
|
|
+ // 确保即使出错也有一个有效的数组
|
|
|
+ if (!Array.isArray(this.comList)) {
|
|
|
+ this.$set(this, 'comList', Array.isArray(val) ? val : []);
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
immediate: true,
|
|
@@ -684,17 +704,46 @@ export default {
|
|
|
|
|
|
// 新增 filterAttrs 方法
|
|
|
filterAttrs(item) {
|
|
|
+ if (!item || !item.dcb_nr) return;
|
|
|
+
|
|
|
// 从 content 中提取所有 {{}} 包裹的 ID
|
|
|
const contentIds = (item.dcb_nr.match(/{{([^}]+)}}/g) || []).map(
|
|
|
(match) => match.slice(2, -2).trim()
|
|
|
);
|
|
|
|
|
|
// 过滤 attrs,只保留在 content 中出现的 ID
|
|
|
- item.attrs = item.attrs.filter((attr) => contentIds.includes(attr.id));
|
|
|
+ if (Array.isArray(item.attrs)) {
|
|
|
+ item.attrs = item.attrs.filter((attr) => contentIds.includes(attr.id));
|
|
|
+ }
|
|
|
},
|
|
|
onAdd(e) {
|
|
|
e.preventDefault();
|
|
|
e.stopPropagation();
|
|
|
+
|
|
|
+ // 确保拖拽的组件数据格式正确
|
|
|
+ const processedList = this.comList.map(item => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ // 确保 attrs 和 dcb_attrs 都是数组
|
|
|
+ attrs: Array.isArray(item.attrs) ? item.attrs : [],
|
|
|
+ dcb_attrs: Array.isArray(item.dcb_attrs)
|
|
|
+ ? item.dcb_attrs
|
|
|
+ : (typeof item.dcb_attrs === 'string'
|
|
|
+ ? JSON.parse(item.dcb_attrs || '[]')
|
|
|
+ : []),
|
|
|
+ // 确保其他必要属性存在
|
|
|
+ content: item.content || item.dcb_nr || '',
|
|
|
+ dcb_nr: item.content || item.dcb_nr || '',
|
|
|
+ type: item.dcb_type || item.type,
|
|
|
+ name: item.dcb_name || item.name,
|
|
|
+ isEdit: item.isEdit || 2
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新组件列表
|
|
|
+ this.$set(this, 'comList', processedList);
|
|
|
+
|
|
|
+ // 触发父组件更新
|
|
|
this.$emit("onRebuild", this.comList);
|
|
|
},
|
|
|
onDragEnd(e) {
|
|
@@ -703,16 +752,26 @@ export default {
|
|
|
this.$emit("onRebuild", this.comList);
|
|
|
},
|
|
|
onUpdate(index, content) {
|
|
|
- let _this = this;
|
|
|
- this.coms[index].content = content;
|
|
|
- // 触发父组件的更新
|
|
|
- this.$emit("onRebuild", this.coms);
|
|
|
- },
|
|
|
- //激活当前层
|
|
|
- onSetActive(e) {
|
|
|
- this.$emit("onSetActiveIndex", e);
|
|
|
+ // 使用实例方法中的 debounce
|
|
|
+ const debouncedUpdate = this.debounce((index, content) => {
|
|
|
+ if (!this.coms || !Array.isArray(this.coms)) {
|
|
|
+ console.warn('coms is not an array');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.coms[index]) {
|
|
|
+ // 使用 Vue.set 确保响应式更新
|
|
|
+ this.$set(this.coms[index], 'content', content);
|
|
|
+ this.$set(this.coms[index], 'dcb_nr', content);
|
|
|
+
|
|
|
+ // 触发父组件的更新
|
|
|
+ this.$emit("onRebuild", this.coms);
|
|
|
+ }
|
|
|
+ }, 300);
|
|
|
+
|
|
|
+ // 调用防抖函数
|
|
|
+ debouncedUpdate(index, content);
|
|
|
},
|
|
|
- // 添加一个辅助方法来验证组件引用
|
|
|
validateComponentRef(ref, index) {
|
|
|
if (!ref) {
|
|
|
throw new Error(`组件引用为空 (index: ${index})`);
|
|
@@ -726,6 +785,20 @@ export default {
|
|
|
if (!ref[0].save) {
|
|
|
throw new Error(`组件没有 save 方法 (index: ${index})`);
|
|
|
}
|
|
|
+ },
|
|
|
+ // 添加防抖函数
|
|
|
+ debounce(fn, delay = 300) {
|
|
|
+ let timer = null;
|
|
|
+ return function(...args) {
|
|
|
+ if (timer) clearTimeout(timer);
|
|
|
+ timer = setTimeout(() => {
|
|
|
+ fn.apply(this, args);
|
|
|
+ }, delay);
|
|
|
+ };
|
|
|
+ },
|
|
|
+ // 添加回之前删除的 onSetActive 方法
|
|
|
+ onSetActive(e) {
|
|
|
+ this.$emit("onSetActiveIndex", e);
|
|
|
}
|
|
|
},
|
|
|
};
|