|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div ref="preview" class="preview">
|
|
|
+ <div ref="previewRoot" class="preview">
|
|
|
<div v-if="heightPrompt" class="height-prompt"></div>
|
|
|
<template v-for="(row, i) in rowList">
|
|
|
<!-- 行 -->
|
|
|
@@ -22,7 +22,7 @@
|
|
|
:class="[type, ...lineClass]"
|
|
|
:style="{ gridArea: type }"
|
|
|
:data-type="type"
|
|
|
- @mousedown="dragStart($event, { cursor, type: type, i, j, k, id: grid.id })"
|
|
|
+ @mousedown="dragStart($event, { cursor, type, i, j, k, id: grid.id })"
|
|
|
></span>
|
|
|
</template>
|
|
|
<component
|
|
|
@@ -30,7 +30,6 @@
|
|
|
:id="grid.id"
|
|
|
ref="preview"
|
|
|
:key="`preview-${grid.id}`"
|
|
|
- @handleHeightChange="handleHeightChange"
|
|
|
:courseware-id="coursewareId"
|
|
|
type="edit"
|
|
|
:class="[grid.id]"
|
|
|
@@ -39,6 +38,7 @@
|
|
|
height: grid.height,
|
|
|
overflow: 'auto',
|
|
|
}"
|
|
|
+ @handleHeightChange="handleHeightChange"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -105,6 +105,7 @@ export default {
|
|
|
lineClass: ['drag-line'],
|
|
|
},
|
|
|
],
|
|
|
+ dragElement: null, // 当前拖拽的组件实例
|
|
|
// 不需要移动的组件
|
|
|
noMoveComponent: ['divider', 'spacing'],
|
|
|
bookInfo: {
|
|
|
@@ -126,7 +127,7 @@ export default {
|
|
|
document.addEventListener('mouseup', this.dragEnd);
|
|
|
},
|
|
|
mounted() {
|
|
|
- const element = this.$refs.preview;
|
|
|
+ const element = this.$refs.previewRoot;
|
|
|
// 监听 courserware 高度变化,获取其高度
|
|
|
this.resizeObserver = new ResizeObserver(() => {
|
|
|
const rect = element.getBoundingClientRect();
|
|
|
@@ -176,82 +177,69 @@ export default {
|
|
|
}
|
|
|
return arr;
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 计算列样式
|
|
|
+ * @param {Object} col 列对象
|
|
|
+ */
|
|
|
computedColStyle(col) {
|
|
|
const grid = col.grid_list;
|
|
|
|
|
|
- let maxCol = 0; // 最大列数
|
|
|
- let rowList = new Map();
|
|
|
- grid.forEach(({ row }) => {
|
|
|
- rowList.set(row, (rowList.get(row) || 0) + 1);
|
|
|
+ // 单次分组:后续 areas / columns / rows 统一复用 rowGroups。
|
|
|
+ const rowGroups = new Map();
|
|
|
+ grid.forEach((item) => {
|
|
|
+ if (!rowGroups.has(item.row)) {
|
|
|
+ rowGroups.set(item.row, []);
|
|
|
+ }
|
|
|
+ rowGroups.get(item.row).push(item);
|
|
|
});
|
|
|
+
|
|
|
+ let maxCol = 0; // 最大列数
|
|
|
let curMaxRow = 0; // 当前数量最大 row 的值
|
|
|
- rowList.forEach((value, key) => {
|
|
|
- if (value > maxCol) {
|
|
|
- maxCol = value;
|
|
|
- curMaxRow = key;
|
|
|
+ rowGroups.forEach((items, row) => {
|
|
|
+ if (items.length > maxCol) {
|
|
|
+ maxCol = items.length;
|
|
|
+ curMaxRow = row;
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ const sortedRows = Array.from(rowGroups.keys()).sort((a, b) => a - b);
|
|
|
+
|
|
|
// 计算 grid_template_areas
|
|
|
let gridTemplateAreas = '';
|
|
|
- let gridArr = [];
|
|
|
- grid.forEach(({ grid_area, row }) => {
|
|
|
- if (!gridArr[row - 1]) {
|
|
|
- gridArr[row - 1] = [];
|
|
|
- }
|
|
|
- if (curMaxRow === row) {
|
|
|
- gridArr[row - 1].push(`${grid_area}`);
|
|
|
- } else {
|
|
|
- let filter = grid.filter((item) => item.row === row);
|
|
|
- let find = filter.findIndex((item) => item.grid_area === grid_area);
|
|
|
- let needNum = maxCol - filter.length; // 需要的数量
|
|
|
+ sortedRows.forEach((row) => {
|
|
|
+ const rowItems = rowGroups.get(row) || [];
|
|
|
+ const needNum = maxCol - rowItems.length; // 需要补齐的数量
|
|
|
+ const splitArr = rowItems.length > 1 ? this.splitInteger(needNum, rowItems.length) : [];
|
|
|
|
|
|
- let str = '';
|
|
|
- if (filter.length === 1) {
|
|
|
- str = ` ${grid_area} `.repeat(needNum + 1);
|
|
|
- } else {
|
|
|
- let arr = this.splitInteger(needNum, filter.length);
|
|
|
- str = arr[find] === 0 ? ` ${grid_area} ` : ` ${grid_area} `.repeat(arr[find] + 1);
|
|
|
+ const areaList = rowItems.map(({ grid_area }, index) => {
|
|
|
+ if (curMaxRow === row) {
|
|
|
+ return `${grid_area}`;
|
|
|
}
|
|
|
- gridArr[row - 1].push(`${str}`);
|
|
|
- }
|
|
|
- });
|
|
|
- gridArr.forEach((item) => {
|
|
|
- gridTemplateAreas += `'${item.join(' ')}' `;
|
|
|
+ if (rowItems.length === 1) {
|
|
|
+ return ` ${grid_area} `.repeat(needNum + 1);
|
|
|
+ }
|
|
|
+ return splitArr[index] === 0 ? ` ${grid_area} ` : ` ${grid_area} `.repeat(splitArr[index] + 1);
|
|
|
+ });
|
|
|
+
|
|
|
+ gridTemplateAreas += `'${areaList.join(' ')}' `;
|
|
|
});
|
|
|
|
|
|
// 计算 grid_template_columns
|
|
|
let gridTemplateColumns = '';
|
|
|
- let max = { row: 0, num: 0 };
|
|
|
- grid.forEach(({ row }) => {
|
|
|
- // 计算出 row 的哪个值最多
|
|
|
- let len = grid.filter((item) => item.row === row).length;
|
|
|
- if (max.num < len) {
|
|
|
- max.num = len;
|
|
|
- max.row = row;
|
|
|
- }
|
|
|
- });
|
|
|
- grid.forEach((item) => {
|
|
|
- if (item.row === max.row) {
|
|
|
- gridTemplateColumns += `${item.width} `;
|
|
|
- }
|
|
|
+ const maxRowItems = rowGroups.get(curMaxRow) || [];
|
|
|
+ maxRowItems.forEach((item) => {
|
|
|
+ gridTemplateColumns += `${item.width} `;
|
|
|
});
|
|
|
|
|
|
// 计算 grid_template_rows
|
|
|
let gridTemplateRows = '';
|
|
|
- // 将 grid 按照 row 分组
|
|
|
- let gridMap = new Map();
|
|
|
- grid.forEach((item) => {
|
|
|
- if (!gridMap.has(item.row)) {
|
|
|
- gridMap.set(item.row, []);
|
|
|
- }
|
|
|
- gridMap.get(item.row).push(item.height);
|
|
|
- });
|
|
|
- gridMap.forEach((value) => {
|
|
|
- if (value.length === 1) {
|
|
|
- gridTemplateRows += `${value[0]} `;
|
|
|
+ sortedRows.forEach((row) => {
|
|
|
+ const heights = (rowGroups.get(row) || []).map((item) => item.height);
|
|
|
+ if (heights.length === 1) {
|
|
|
+ gridTemplateRows += `${heights[0]} `;
|
|
|
} else {
|
|
|
- let isAllAuto = value.every((item) => item === 'auto'); // 是否全是 auto
|
|
|
- gridTemplateRows += isAllAuto ? 'auto ' : `max(${value.join(', ')}) `;
|
|
|
+ const isAllAuto = heights.every((item) => item === 'auto'); // 是否全是 auto
|
|
|
+ gridTemplateRows += isAllAuto ? 'auto ' : `max(${heights.join(', ')}) `;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
@@ -273,6 +261,10 @@ export default {
|
|
|
* @param {number} k
|
|
|
*/
|
|
|
dragStart(event, { cursor, type, id, i, j, k }) {
|
|
|
+ const dragElement = this.findChildComponentByKey(`preview-${id}`);
|
|
|
+ if (!dragElement) return;
|
|
|
+ this.dragElement = dragElement;
|
|
|
+
|
|
|
const { clientX, clientY } = event;
|
|
|
this.drag = {
|
|
|
dragging: true,
|
|
|
@@ -285,7 +277,6 @@ export default {
|
|
|
k,
|
|
|
};
|
|
|
|
|
|
- this.bgColor = '#272727';
|
|
|
document.body.style.cursor = cursor;
|
|
|
},
|
|
|
/**
|
|
|
@@ -300,11 +291,10 @@ export default {
|
|
|
const offsetX = clientX - startX;
|
|
|
const offsetY = clientY - startY;
|
|
|
|
|
|
- let el = this.findChildComponentByKey(`preview-${id}`);
|
|
|
- let { min_height, min_width } = el.data;
|
|
|
+ let { min_height, min_width } = this.dragElement.data;
|
|
|
+
|
|
|
+ const ROW_WIDTH = 1000;
|
|
|
|
|
|
- // 获取行的宽度
|
|
|
- const row_width = document.getElementsByClassName(`row-${i}`)[0].getBoundingClientRect().width;
|
|
|
this.$emit('computedMoveData', {
|
|
|
i,
|
|
|
j,
|
|
|
@@ -315,7 +305,7 @@ export default {
|
|
|
id,
|
|
|
min_width,
|
|
|
min_height,
|
|
|
- row_width,
|
|
|
+ row_width: ROW_WIDTH,
|
|
|
});
|
|
|
|
|
|
this.drag.startX = clientX;
|
|
|
@@ -332,9 +322,13 @@ export default {
|
|
|
startX: 0,
|
|
|
startY: 0,
|
|
|
type: '',
|
|
|
+ id: '',
|
|
|
+ i: -1,
|
|
|
+ j: -1,
|
|
|
+ k: -1,
|
|
|
};
|
|
|
|
|
|
- this.bgColor = '#ebebeb';
|
|
|
+ this.dragElement = null;
|
|
|
document.body.style.cursor = 'auto';
|
|
|
},
|
|
|
// 获取子组件
|