|
@@ -20,7 +20,13 @@
|
|
|
<div :key="i" class="row" :style="getMultipleColStyle(i)">
|
|
|
<!-- 列 -->
|
|
|
<template v-for="(col, j) in row.col_list">
|
|
|
- <span v-if="j === 0" :key="`start-${i}-${j}`" class="drag-vertical-line" :data-row="i" :data-col="j"></span>
|
|
|
+ <span
|
|
|
+ v-if="j === 0"
|
|
|
+ :key="`start-${i}-${j}`"
|
|
|
+ class="drag-vertical-line col-start"
|
|
|
+ :data-row="i"
|
|
|
+ :data-col="j"
|
|
|
+ ></span>
|
|
|
<div
|
|
|
:key="j"
|
|
|
:class="['col', `col-${i}-${j}`]"
|
|
@@ -35,11 +41,22 @@
|
|
|
<template v-for="(grid, k) in col.grid_list">
|
|
|
<span
|
|
|
v-if="k === 0"
|
|
|
- :key="`start-${k}`"
|
|
|
- class="drag-line grid-line"
|
|
|
+ :key="`start-${i}-${j}-${k}`"
|
|
|
+ class="drag-line grid-line drag-row"
|
|
|
+ :style="{ gridArea: 'grid-top' }"
|
|
|
:data-row="i"
|
|
|
:data-col="j"
|
|
|
:data-grid="k"
|
|
|
+ data-type="row"
|
|
|
+ ></span>
|
|
|
+ <span
|
|
|
+ :key="`left-${k}`"
|
|
|
+ :style="{ gridArea: `left-${grid.grid_area}` }"
|
|
|
+ :data-row="i"
|
|
|
+ :data-col="j"
|
|
|
+ :data-grid="k"
|
|
|
+ data-type="col-left"
|
|
|
+ class="drag-vertical-line grid-line grid-line-left"
|
|
|
></span>
|
|
|
<component
|
|
|
:is="componentList[grid.type]"
|
|
@@ -47,15 +64,33 @@
|
|
|
ref="component"
|
|
|
:key="k"
|
|
|
:class="[grid.id]"
|
|
|
- :style="{ gridArea: grid.grid_area, height: grid.height }"
|
|
|
+ :style="{ gridArea: grid.grid_area, height: grid.height, marginTop: grid.row !== 1 ? '16px' : '0' }"
|
|
|
:delete-component="deleteComponent(i, j, k)"
|
|
|
:component-move="componentMove(i, j, k)"
|
|
|
@showSetting="showSetting"
|
|
|
/>
|
|
|
- <span :key="`end-${k}`" class="drag-line grid-line" :data-row="i" :data-col="j" :data-grid="k + 1"></span>
|
|
|
+ <span
|
|
|
+ :key="`right-${k}`"
|
|
|
+ :style="{ gridArea: `right-${grid.grid_area}` }"
|
|
|
+ :data-row="i"
|
|
|
+ :data-col="j"
|
|
|
+ :data-grid="k + 1"
|
|
|
+ data-type="col-right"
|
|
|
+ class="drag-vertical-line grid-line grid-line-right"
|
|
|
+ ></span>
|
|
|
+ <span
|
|
|
+ v-if="k === col.grid_list.length - 1"
|
|
|
+ :key="`end-${i}-${j}-${k}`"
|
|
|
+ class="drag-line grid-line drag-row"
|
|
|
+ :style="{ gridArea: `grid-bottom` }"
|
|
|
+ :data-row="i"
|
|
|
+ :data-col="j"
|
|
|
+ :data-grid="k + 1"
|
|
|
+ data-type="row"
|
|
|
+ ></span>
|
|
|
</template>
|
|
|
</div>
|
|
|
- <span :key="`end-${i}-${j}`" class="drag-vertical-line" :data-row="i" :data-col="j + 1"></span>
|
|
|
+ <span :key="`end-${i}-${j}`" class="drag-vertical-line col-end" :data-row="i" :data-col="j + 1"></span>
|
|
|
</template>
|
|
|
</div>
|
|
|
<span v-if="i < data.row_list.length - 1" :key="`row-${i}`" class="drag-line" :data-row="i"></span>
|
|
@@ -94,6 +129,7 @@ export default {
|
|
|
curRow: -2,
|
|
|
curCol: -1,
|
|
|
curGrid: -1,
|
|
|
+ gridInsertType: '', // 网格插入类型
|
|
|
enterCanvas: false, // 是否进入画布
|
|
|
// 拖拽状态
|
|
|
drag: {
|
|
@@ -128,6 +164,7 @@ export default {
|
|
|
});
|
|
|
this.curCol = -1;
|
|
|
this.curGrid = -1;
|
|
|
+ this.gridInsertType = '';
|
|
|
},
|
|
|
},
|
|
|
},
|
|
@@ -252,7 +289,10 @@ export default {
|
|
|
*/
|
|
|
deleteComponent(i, j, k) {
|
|
|
return () => {
|
|
|
- this.data.row_list[i].col_list[j].grid_list.splice(k, 1);
|
|
|
+ const gridList = this.data.row_list[i].col_list[j].grid_list;
|
|
|
+ let delRow = gridList[k].row; // 删除的 grid 的 row
|
|
|
+ let delW = gridList[k].width; // 删除的 grid 的 width
|
|
|
+ gridList.splice(k, 1);
|
|
|
|
|
|
const colList = this.data.row_list[i].col_list[j];
|
|
|
if (colList.grid_list.length === 0) {
|
|
@@ -269,14 +309,69 @@ export default {
|
|
|
this.data.row_list.splice(i, 1);
|
|
|
}
|
|
|
|
|
|
- const gridList = this.data.row_list[i]?.col_list[j]?.grid_list;
|
|
|
if (gridList?.length > 0) {
|
|
|
- colList.grid_template_columns = `100%`;
|
|
|
-
|
|
|
- const grid_template_areas = gridList.map(({ grid_area }) => grid_area).join(' ');
|
|
|
- colList.grid_template_areas = `'.' '${grid_template_areas}' '.'`;
|
|
|
+ let maxCol = 0; // 最大列数
|
|
|
+ let rowList = new Map();
|
|
|
+ gridList.forEach(({ row }) => {
|
|
|
+ rowList.set(row, (rowList.get(row) || 0) + 1);
|
|
|
+ });
|
|
|
+ let curMaxRow = 0; // 当前数量最大 row 的值
|
|
|
+ rowList.forEach((value, key) => {
|
|
|
+ if (value > maxCol) {
|
|
|
+ maxCol = value;
|
|
|
+ curMaxRow = key;
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- colList.grid_template_rows = `0 ${gridList.map(({ height }) => height).join(' 16px ')} 0`;
|
|
|
+ let delNum = gridList.filter(({ row }) => row === delRow).length;
|
|
|
+ let diff = Number(delW.replace('%', '')) / delNum;
|
|
|
+ if (delNum === 0) {
|
|
|
+ // 删除 grid 后面的 row 都减 1
|
|
|
+ gridList.forEach((item) => {
|
|
|
+ if (item.row > delRow) {
|
|
|
+ item.row -= 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ gridList.forEach((item) => {
|
|
|
+ if (item.row === delRow) {
|
|
|
+ item.width = `${Number(item.width.replace('%', '')) + diff}%`;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 计算 grid_template_areas 和 grid_template_rows
|
|
|
+ let gridStr = '';
|
|
|
+ let gridArr = [];
|
|
|
+ gridList.forEach(({ grid_area, row }) => {
|
|
|
+ if (!gridArr[row - 1]) {
|
|
|
+ gridArr[row - 1] = [];
|
|
|
+ }
|
|
|
+ if (curMaxRow === row) {
|
|
|
+ gridArr[row - 1].push(`left-${grid_area} ${grid_area} right-${grid_area}`);
|
|
|
+ } else {
|
|
|
+ const str = ` ${grid_area} `.repeat(maxCol * 3 - 2);
|
|
|
+ gridArr[row - 1].push(`left-${grid_area} ${str} right-${grid_area}`);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ gridArr.forEach((item) => {
|
|
|
+ gridStr += `'${item.join(' ')}' `;
|
|
|
+ });
|
|
|
+ colList.grid_template_areas = `'${'grid-top '.repeat(maxCol * 3)}' ${gridStr} '${'grid-bottom '.repeat(maxCol * 3)}'`;
|
|
|
+ colList.grid_template_rows = `0 ${gridList.map(({ height }) => height).join(' ')} 0`;
|
|
|
+
|
|
|
+ // 计算 grid_template_columns
|
|
|
+ let gridTemCols = '';
|
|
|
+ gridList.forEach((item) => {
|
|
|
+ // 如果第一行只有一个 grid 则不需要 - 8px
|
|
|
+ if (maxCol === 1 && item.row === 1) {
|
|
|
+ gridTemCols += `${item.width}`;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (item.row === 1) {
|
|
|
+ gridTemCols += `calc(${item.width} - 8px) 8px 8px `;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ colList.grid_template_columns = `0 ${maxCol === 1 ? gridTemCols : gridTemCols.slice(0, gridTemCols.length - 8)} 0`;
|
|
|
}
|
|
|
};
|
|
|
},
|
|
@@ -343,6 +438,7 @@ export default {
|
|
|
this.curRow = Number(item.getAttribute('data-row'));
|
|
|
this.curCol = Number(item.getAttribute('data-col') || -1);
|
|
|
this.curGrid = Number(item.getAttribute('data-grid') || -1);
|
|
|
+ this.gridInsertType = item.getAttribute('data-type') || '';
|
|
|
|
|
|
item.style.opacity = 1;
|
|
|
} else {
|
|
@@ -408,16 +504,90 @@ export default {
|
|
|
let row = this.data.row_list[this.curRow];
|
|
|
let col = row.col_list[this.curCol];
|
|
|
let grid = col.grid_list;
|
|
|
+ let type = this.gridInsertType;
|
|
|
+
|
|
|
+ if (type === 'row') {
|
|
|
+ let rowNum = this.curGrid === 0 ? 1 : grid[this.curGrid - 1].row + 1;
|
|
|
+ grid.splice(this.curGrid, 0, {
|
|
|
+ id,
|
|
|
+ grid_area: letter,
|
|
|
+ width: '100%',
|
|
|
+ height: 'auto',
|
|
|
+ row: rowNum,
|
|
|
+ type: this.curType,
|
|
|
+ });
|
|
|
+ // 在新加入的 grid 后面的 row 都加 1
|
|
|
+ grid.forEach((item, i) => {
|
|
|
+ if (i > this.curGrid) {
|
|
|
+ item.row += 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- grid.splice(this.curGrid, 0, {
|
|
|
- id,
|
|
|
- grid_area: letter,
|
|
|
- width: '100%',
|
|
|
- height: 'auto',
|
|
|
- type: this.curType,
|
|
|
+ if (['col-left', 'col-right'].includes(type)) {
|
|
|
+ let rowNum = grid[type === 'col-left' ? this.curGrid : this.curGrid - 1].row;
|
|
|
+ grid.splice(this.curGrid, 0, {
|
|
|
+ id,
|
|
|
+ grid_area: letter,
|
|
|
+ width: '100%',
|
|
|
+ height: 'auto',
|
|
|
+ row: rowNum,
|
|
|
+ type: this.curType,
|
|
|
+ });
|
|
|
+
|
|
|
+ let allRowNum = grid.filter(({ row }) => row === rowNum).length;
|
|
|
+ let w = 0;
|
|
|
+ grid.forEach((item, i) => {
|
|
|
+ if (item.row === rowNum && i !== this.curGrid) {
|
|
|
+ let width = Number(item.width.replace('%', ''));
|
|
|
+ let diff = width / allRowNum;
|
|
|
+ item.width = `${width - diff}%`;
|
|
|
+ w += diff;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ grid[this.curGrid].width = `${w}%`;
|
|
|
+ }
|
|
|
+
|
|
|
+ let maxCol = 0; // 最大列数
|
|
|
+ let rowList = new Map();
|
|
|
+ grid.forEach(({ row }) => {
|
|
|
+ rowList.set(row, (rowList.get(row) || 0) + 1);
|
|
|
+ });
|
|
|
+ let curMaxRow = 0; // 当前数量最大 row 的值
|
|
|
+ rowList.forEach((value, key) => {
|
|
|
+ if (value > maxCol) {
|
|
|
+ maxCol = value;
|
|
|
+ curMaxRow = key;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 计算 grid_template_areas 和 grid_template_rows
|
|
|
+ let gridStr = '';
|
|
|
+ let gridArr = [];
|
|
|
+ grid.forEach(({ grid_area, row }) => {
|
|
|
+ if (!gridArr[row - 1]) {
|
|
|
+ gridArr[row - 1] = [];
|
|
|
+ }
|
|
|
+ if (curMaxRow === row) {
|
|
|
+ gridArr[row - 1].push(`left-${grid_area} ${grid_area} right-${grid_area}`);
|
|
|
+ } else {
|
|
|
+ const str = ` ${grid_area} `.repeat(maxCol * 3 - 2);
|
|
|
+ gridArr[row - 1].push(`left-${grid_area} ${str} right-${grid_area}`);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ gridArr.forEach((item) => {
|
|
|
+ gridStr += `'${item.join(' ')}' `;
|
|
|
+ });
|
|
|
+ col.grid_template_areas = `'${'grid-top '.repeat(maxCol * 3)}' ${gridStr} '${'grid-bottom '.repeat(maxCol * 3)}'`;
|
|
|
+ col.grid_template_rows = `0 ${grid.map(({ height }) => height).join(' ')} 0`;
|
|
|
+
|
|
|
+ // 计算 grid_template_columns
|
|
|
+ let gridTemCols = '';
|
|
|
+ grid.forEach((item) => {
|
|
|
+ if (item.row === 1) {
|
|
|
+ gridTemCols += `calc(${item.width} - 8px) 8px 8px `;
|
|
|
+ }
|
|
|
});
|
|
|
- col.grid_template_areas = `'.' ${grid.map(({ grid_area }) => `'${grid_area}'`).join(" '.' ")} '.'`;
|
|
|
- col.grid_template_rows = `0 ${grid.map(({ height }) => height).join(' 16px ')} 0`;
|
|
|
+ col.grid_template_columns = `0 ${gridTemCols.slice(0, gridTemCols.length - 8)} 0`;
|
|
|
},
|
|
|
/**
|
|
|
* 计算列插入的对象
|
|
@@ -441,13 +611,14 @@ export default {
|
|
|
col.splice(this.curCol, 0, {
|
|
|
width: '100%',
|
|
|
height: 'auto',
|
|
|
- grid_template_areas: `'.' '${letter}' '.'`,
|
|
|
- grid_template_columns: '100%',
|
|
|
+ grid_template_areas: `'grid-top grid-top grid-top' 'left-${letter} ${letter} right-${letter}' 'grid-bottom grid-bottom grid-bottom'`,
|
|
|
+ grid_template_columns: '0 100% 0',
|
|
|
grid_template_rows: '0 auto 0',
|
|
|
grid_list: [
|
|
|
{
|
|
|
id,
|
|
|
grid_area: letter,
|
|
|
+ row: 1,
|
|
|
width: '100%',
|
|
|
height: 'auto',
|
|
|
type: this.curType,
|
|
@@ -468,8 +639,8 @@ export default {
|
|
|
{
|
|
|
width: '100%',
|
|
|
height: 'auto',
|
|
|
- grid_template_areas: `'.' '${letter}' '.'`,
|
|
|
- grid_template_columns: '100%',
|
|
|
+ grid_template_areas: `'grid-top grid-top grid-top' 'left-${letter} ${letter} right-${letter}' 'grid-bottom grid-bottom grid-bottom'`,
|
|
|
+ grid_template_columns: '0 100% 0',
|
|
|
grid_template_rows: '0 auto 0',
|
|
|
grid_list: [
|
|
|
{
|
|
@@ -477,6 +648,7 @@ export default {
|
|
|
grid_area: letter,
|
|
|
width: '100%',
|
|
|
height: 'auto',
|
|
|
+ row: 1,
|
|
|
type: this.curType,
|
|
|
},
|
|
|
],
|
|
@@ -526,10 +698,18 @@ export default {
|
|
|
display: grid;
|
|
|
row-gap: 16px;
|
|
|
|
|
|
- > .drag-vertical-line:not(:first-child, :last-child) {
|
|
|
+ > .drag-vertical-line:not(:first-child, :last-child, .grid-line) {
|
|
|
left: 6px;
|
|
|
}
|
|
|
|
|
|
+ .drag-vertical-line.col-start {
|
|
|
+ left: -12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .drag-vertical-line.col-end {
|
|
|
+ right: -8px;
|
|
|
+ }
|
|
|
+
|
|
|
.col {
|
|
|
display: grid;
|
|
|
|
|
@@ -537,7 +717,7 @@ export default {
|
|
|
left: -8px;
|
|
|
}
|
|
|
|
|
|
- .drag-vertical-line:not(:first-child, :last-child) {
|
|
|
+ .drag-vertical-line:not(:first-child, :last-child, .grid-line) {
|
|
|
left: 6px;
|
|
|
}
|
|
|
|
|
@@ -548,6 +728,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
.drag-line {
|
|
|
+ z-index: 9;
|
|
|
width: calc(100% - 16px);
|
|
|
height: 4px;
|
|
|
margin: 0 8px;
|
|
@@ -555,6 +736,10 @@ export default {
|
|
|
border-radius: 4px;
|
|
|
opacity: 0;
|
|
|
|
|
|
+ &.drag-row {
|
|
|
+ background-color: $right-color;
|
|
|
+ }
|
|
|
+
|
|
|
&.grid-line:not(:first-child, :last-child) {
|
|
|
position: relative;
|
|
|
top: 6px;
|
|
@@ -563,11 +748,16 @@ export default {
|
|
|
|
|
|
.drag-vertical-line {
|
|
|
position: relative;
|
|
|
+ z-index: 9;
|
|
|
width: 4px;
|
|
|
height: 100%;
|
|
|
background-color: #379fff;
|
|
|
border-radius: 4px;
|
|
|
opacity: 0;
|
|
|
+
|
|
|
+ &.grid-line {
|
|
|
+ background-color: #f43;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
@@ -581,6 +771,7 @@ export default {
|
|
|
background-color: #eaf5ff;
|
|
|
border: 1px solid #b5dbff;
|
|
|
border-radius: 4px;
|
|
|
+ opacity: 0.5;
|
|
|
transform: translate(-40%, -40%);
|
|
|
}
|
|
|
</style>
|