|
|
@@ -59,7 +59,8 @@
|
|
|
ref="component"
|
|
|
:key="`grid-${grid.id}`"
|
|
|
:old-id="grid?.oldId"
|
|
|
- :class="[grid.id]"
|
|
|
+ :class="['grid', grid.id]"
|
|
|
+ :data-id="grid.id"
|
|
|
:data-row="i"
|
|
|
:data-col="j"
|
|
|
:data-grid="k"
|
|
|
@@ -128,6 +129,7 @@ import {
|
|
|
} from '@/api/book';
|
|
|
import _ from 'lodash';
|
|
|
import { unified_attrib } from '@/common/data';
|
|
|
+import { waitLayoutStable } from '@/utils/common';
|
|
|
|
|
|
import PreviewEdit from './PreviewEdit.vue';
|
|
|
|
|
|
@@ -187,6 +189,8 @@ export default {
|
|
|
title_list: [],
|
|
|
curComponentId: '', // 当前选中组件 id
|
|
|
projectResourcePopedom: [], // 当前编辑人员的项目资源权限
|
|
|
+ componentsDataLoaded: false, // 组件数据是否加载完成
|
|
|
+ visible_id: this.$route.query.visible_id, // 可见组件 id
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -313,6 +317,30 @@ export default {
|
|
|
},
|
|
|
deep: true,
|
|
|
},
|
|
|
+ componentsDataLoaded: {
|
|
|
+ async handler(val) {
|
|
|
+ if (val && this.visible_id) {
|
|
|
+ await this.$nextTick();
|
|
|
+ let isAllLoader = false;
|
|
|
+ if (this.$refs?.component === undefined || this.$refs?.component.length === 0) {
|
|
|
+ isAllLoader = true;
|
|
|
+ } else {
|
|
|
+ isAllLoader = this.$refs?.component?.every((item) => item.property.isGetContent);
|
|
|
+ }
|
|
|
+ if (isAllLoader) {
|
|
|
+ this.visibleIdScrollIntoView();
|
|
|
+ } else {
|
|
|
+ let checkInterval = setInterval(() => {
|
|
|
+ let isAllLoader = this.$refs?.component?.every((item) => item.property.isGetContent);
|
|
|
+ if (isAllLoader) {
|
|
|
+ clearInterval(checkInterval);
|
|
|
+ this.visibleIdScrollIntoView();
|
|
|
+ }
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
},
|
|
|
created() {
|
|
|
const loading = this.$loading({
|
|
|
@@ -334,6 +362,7 @@ export default {
|
|
|
} else {
|
|
|
this.data = parsedContent;
|
|
|
}
|
|
|
+ this.componentsDataLoaded = true;
|
|
|
loading.close();
|
|
|
}
|
|
|
if (content_group_row_list) this.content_group_row_list = JSON.parse(content_group_row_list);
|
|
|
@@ -369,6 +398,21 @@ export default {
|
|
|
},
|
|
|
methods: {
|
|
|
/**
|
|
|
+ * 将可见组件滚动到视图中心
|
|
|
+ */
|
|
|
+ async visibleIdScrollIntoView() {
|
|
|
+ await this.$nextTick();
|
|
|
+ const componentNum = this.$refs?.component?.length || 0;
|
|
|
+ const frames = Math.ceil(componentNum / 10); // 每10个组件为一帧,计算需要等待的帧数
|
|
|
+ await waitLayoutStable(frames);
|
|
|
+
|
|
|
+ const target = this.findChildComponentByKey(`grid-${this.visible_id}`);
|
|
|
+ const targetElement = target?.$el || target;
|
|
|
+ if (targetElement && typeof targetElement.scrollIntoView === 'function') {
|
|
|
+ targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
* 监听复制事件,触发复制组件方法
|
|
|
* @param {KeyboardEvent} event 键盘事件
|
|
|
*/
|
|
|
@@ -630,7 +674,7 @@ export default {
|
|
|
|
|
|
this.$message.success('保存成功');
|
|
|
if (type === 'quit') {
|
|
|
- this.$emit('back');
|
|
|
+ this.$emit('back', this.getFirstVisibleComponentId());
|
|
|
}
|
|
|
if (type === 'edit') {
|
|
|
this.$emit('changeEditStatus');
|
|
|
@@ -640,6 +684,34 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
/**
|
|
|
+ * 获取 create-middle 视口内第一个可见的组件 id
|
|
|
+ * @returns {string} 第一个可见组件 id;不存在时返回空字符串
|
|
|
+ */
|
|
|
+ getFirstVisibleComponentId() {
|
|
|
+ const container = document.querySelector('.create-middle');
|
|
|
+ if (!container) return '';
|
|
|
+
|
|
|
+ const containerRect = container.getBoundingClientRect();
|
|
|
+ const gridElements = container.querySelectorAll('.canvas .grid[data-id]');
|
|
|
+
|
|
|
+ let firstVisibleId = '';
|
|
|
+ let minTop = Number.POSITIVE_INFINITY; // 初始化为正无穷大,以确保任何可见元素的 top 都会小于它
|
|
|
+
|
|
|
+ gridElements.forEach((el) => {
|
|
|
+ const rect = el.getBoundingClientRect();
|
|
|
+ const visibleHeight = Math.min(rect.bottom, containerRect.bottom) - Math.max(rect.top, containerRect.top);
|
|
|
+
|
|
|
+ const isVisible = visibleHeight > 0;
|
|
|
+
|
|
|
+ if (isVisible && rect.top < minTop) {
|
|
|
+ minTop = rect.top;
|
|
|
+ firstVisibleId = el.dataset.id || '';
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return firstVisibleId;
|
|
|
+ },
|
|
|
+ /**
|
|
|
* 显示设置
|
|
|
* @param {object} setting 组件设置数据
|
|
|
* @param {string} type 组件类型
|