<template>
|
<div style="height:100%;background:#fff;">
|
<div
|
ref="moveBlock"
|
style="position:absolute;top:0px;left:0px;height:0px;width:0px;background:#f4f6fc;text-align:center;z-index: 9999;font-size:12px;"
|
></div>
|
<div class="test-item-main">
|
<div class="test-item-main-left">
|
<div class="layout-field">
|
<div class="field-title">布局字段</div>
|
<div
|
v-layoutdrag="{
|
belongDiv: 'groupLayOutDiv',
|
setMoveBlock: setMoveBlock,
|
initMoveBlock: initMoveBlock,
|
getInitMoveBlock: getInitMoveBlock,
|
getScrollDistance: getScrollDistance,
|
findAppropriatePosition: findAppropriatePosition,
|
setAppropriatePosition: setAppropriatePosition
|
}"
|
class="field-label"
|
id="0"
|
ref="groupLayOutDiv"
|
>
|
<i class="el-icon-menu"></i
|
><span style="margin-left:3px;">分组</span>
|
</div>
|
</div>
|
<div class="item-field">
|
<div class="field-title">检测项字段</div>
|
<div class="item-field-table" ref="itemLayOutDiv">
|
<div
|
v-for="(item, index) in checkItems"
|
:key="item.id"
|
class="item-field-div"
|
>
|
<el-checkbox v-model="checked"></el-checkbox>
|
<div
|
v-layoutdrag="{
|
belongDiv: 'itemLayOutDiv',
|
setMoveBlock: setMoveBlock,
|
initMoveBlock: initMoveBlock,
|
getInitMoveBlock: getInitMoveBlock,
|
getScrollDistance: getScrollDistance,
|
findAppropriatePosition: findAppropriatePosition,
|
setAppropriatePosition: setAppropriatePosition
|
}"
|
class="item-field-label-div"
|
:id="item.id"
|
>
|
{{ item.name }}
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="test-item-main-middle">
|
<div class="test-item-main-middle-header">
|
<el-button
|
type="text"
|
icon="el-icon-check"
|
size="medium"
|
style="color:#67c23a"
|
@click="submitJson"
|
>提交</el-button
|
>
|
<el-button
|
type="text"
|
icon="el-icon-view"
|
size="medium"
|
@click="previewLayOut"
|
>预览</el-button
|
><el-button
|
type="text"
|
icon="el-icon-delete"
|
size="medium"
|
style="color:#f56c6c"
|
@click="cleanLayOut"
|
>清空</el-button
|
>
|
</div>
|
<div class="test-item-main-middle-body" ref="layOutContentDiv">
|
<el-row
|
:gutter="5"
|
v-for="(rowItem, i) in layOutItems"
|
:key="rowItem.uniqueId"
|
>
|
<div
|
:ref="'body_row_' + rowItem.uniqueId"
|
:style="'min-height:' + rowItem.minHeight + 'px'"
|
>
|
<el-col
|
:span="colItem.span"
|
v-for="(colItem, k) in rowItem.cols"
|
:key="colItem.uniqueId"
|
>
|
<div
|
style="background:#ecf5ff;"
|
:ref="'body_col_' + colItem.uniqueId"
|
:class="[colItem.isSelect ? 'selected-item' : '']"
|
>
|
<div
|
v-if="colItem.type === 'item'"
|
style="position:relative;"
|
>
|
<div @click="itemClick(colItem.uniqueId, 'firstCol')">
|
<div class="col-title">
|
<div
|
v-layoutdrag="{
|
belongDiv: 'itemTitleDiv',
|
setMoveBlock: setMoveBlock,
|
initMoveBlock: initMoveBlock,
|
getInitMoveBlock: getInitMoveBlock,
|
getScrollDistance: getScrollDistance,
|
findAppropriatePosition: findAppropriatePosition,
|
setAppropriatePosition: setAppropriatePosition,
|
itemClick: itemClick,
|
uniqueId: colItem.uniqueId,
|
colType: 'firstCol'
|
}"
|
style="cursor: move;width:calc(100% - 18px)"
|
:title="colItem.label"
|
:id="colItem.uniqueId"
|
>
|
{{ colItem.label }}
|
</div>
|
<!--<div
|
style="width:18px;text-align:center;line-height:18px;background:#fff;color:#fff;border:1px solid #dcdfe6;cursor: pointer;"
|
></div>-->
|
<div
|
style="width:18px;text-align:center;line-height:18px;background:#67c23a;color:#fff;cursor: pointer;"
|
>
|
✓
|
</div>
|
<!--<div
|
style="width:18px;text-align:center;line-height:18px;background:#f56c6c;color:#fff;cursor: pointer;"
|
>
|
✕
|
</div>-->
|
</div>
|
<div class="col-remark">
|
{{ colItem.remark }}
|
</div>
|
<div>
|
<el-input
|
class="item-input"
|
v-model="inputVal1"
|
placeholder="请输入内容"
|
></el-input>
|
</div>
|
</div>
|
<el-button
|
v-show="colItem.isSelect"
|
type="danger"
|
icon="el-icon-delete"
|
circle
|
style="position:absolute;bottom: -8px;right:0px;width: 20px;height: 20px;padding:3px;z-index:999;"
|
@click.stop="delItem('0', i, k, null, null)"
|
></el-button>
|
</div>
|
<div v-else style="position:relative;">
|
<div>
|
<div class="group-title">
|
<div
|
v-layoutdrag="{
|
belongDiv: 'groupTitleDiv',
|
setMoveBlock: setMoveBlock,
|
initMoveBlock: initMoveBlock,
|
getInitMoveBlock: getInitMoveBlock,
|
getScrollDistance: getScrollDistance,
|
findAppropriatePosition: findAppropriatePosition,
|
setAppropriatePosition: setAppropriatePosition,
|
itemClick: itemClick,
|
uniqueId: colItem.uniqueId,
|
colType: 'firstCol'
|
}"
|
style="cursor: move;line-height:30px;font-weight:bold;text-align:center;"
|
:id="colItem.uniqueId"
|
>
|
{{ colItem.label }}
|
</div>
|
</div>
|
<div class="group-item">
|
<el-row
|
:gutter="5"
|
v-for="(child, j) in colItem.children"
|
:key="child.uniqueId"
|
>
|
<div
|
:ref="'body_row_' + child.uniqueId"
|
class="test-item-row-div"
|
>
|
<el-col
|
:span="childCol.span"
|
v-for="(childCol, m) in child.cols"
|
:key="childCol.uniqueId"
|
>
|
<div style="position:relative;">
|
<div
|
style="background:#f4f6fc;"
|
:ref="'body_col_' + childCol.uniqueId"
|
@click="
|
itemClick(childCol.uniqueId, 'secondCol')
|
"
|
:class="[
|
childCol.isSelect ? 'selected-item' : ''
|
]"
|
>
|
<div class="col-title">
|
<div
|
v-layoutdrag="{
|
belongDiv: 'groupItemTitleDiv',
|
setMoveBlock: setMoveBlock,
|
initMoveBlock: initMoveBlock,
|
getInitMoveBlock: getInitMoveBlock,
|
getScrollDistance: getScrollDistance,
|
findAppropriatePosition: findAppropriatePosition,
|
setAppropriatePosition: setAppropriatePosition,
|
itemClick: itemClick,
|
uniqueId: childCol.uniqueId,
|
colType: 'secondCol'
|
}"
|
style="cursor: move;width:calc(100% - 18px)"
|
:title="childCol.label"
|
:id="childCol.uniqueId"
|
>
|
{{ childCol.label }}
|
</div>
|
<!--<div
|
style="width:18px;text-align:center;line-height:18px;background:#fff;color:#fff;border:1px solid #dcdfe6;cursor: pointer;"
|
></div>-->
|
<div
|
style="width:18px;text-align:center;line-height:18px;background:#67c23a;color:#fff;cursor: pointer;"
|
>
|
✓
|
</div>
|
<!--<div
|
style="width:18px;text-align:center;line-height:18px;background:#f56c6c;color:#fff;cursor: pointer;"
|
>
|
✕
|
</div>-->
|
</div>
|
<div>
|
<el-input
|
class="item-input"
|
v-model="inputVal"
|
placeholder="请输入内容"
|
></el-input>
|
</div>
|
</div>
|
<el-button
|
v-show="childCol.isSelect"
|
type="danger"
|
icon="el-icon-delete"
|
circle
|
style="position:absolute;bottom: -8px;right:0px;width: 20px;height: 20px;padding:3px;z-index:999;"
|
@click.stop="delItem('1', i, k, j, m)"
|
></el-button>
|
</div>
|
</el-col>
|
</div>
|
</el-row>
|
</div>
|
</div>
|
<el-button
|
v-show="colItem.isSelect"
|
type="danger"
|
icon="el-icon-delete"
|
circle
|
style="position:absolute;bottom: -8px;right:0px;width: 20px;height: 20px;padding:3px;z-index:999;"
|
@click.stop="delItem('2', i, k, null, null)"
|
></el-button>
|
</div>
|
</div>
|
</el-col>
|
</div>
|
</el-row>
|
</div>
|
</div>
|
<div class="test-item-main-right">
|
<div class="test-item-main-right-header">
|
字段属性
|
</div>
|
<div class="test-item-main-right-body">
|
<div class="test-item-main-right-body-title">
|
<span>标题:</span
|
><el-input
|
v-model="itemTitle"
|
placeholder="请输入内容"
|
@input="titleChange"
|
></el-input>
|
</div>
|
<div class="test-item-main-right-body-width">
|
<span>宽度:</span>
|
<el-input-number
|
v-model="widthNum"
|
controls-position="right"
|
@change="widthChange"
|
:min="3"
|
:max="24"
|
></el-input-number>
|
</div>
|
</div>
|
</div>
|
</div>
|
<previewLayout
|
:currshowlist.sync="showPreviewLayout"
|
:layOutJson="layOutJson"
|
/>
|
</div>
|
</template>
|
<style lang="scss" scoped>
|
.test-item-main {
|
-webkit-user-select: none;
|
-moz-user-select: none;
|
-ms-user-select: none;
|
user-select: none;
|
}
|
.test-item-main {
|
display: flex;
|
justify-content: space-around;
|
height: 100%;
|
}
|
.test-item-main-left {
|
width: 17%;
|
padding-left: 10px;
|
padding-top: 30px;
|
}
|
.layout-field {
|
height: 80px;
|
}
|
.item-field {
|
height: calc(100% - 80px);
|
}
|
.field-title {
|
font-size: 13px;
|
height: 30px;
|
line-height: 30px;
|
}
|
.field-label {
|
width: 120px;
|
font-size: 12px;
|
height: 29px;
|
line-height: 29px;
|
cursor: move;
|
background: #f4f6fc;
|
border: 1px solid #f4f6fc;
|
}
|
.field-label:hover {
|
border: 1px dashed #409eff;
|
}
|
.item-field-table {
|
height: calc(100% - 30px);
|
}
|
.item-field-div {
|
display: flex;
|
height: 29px;
|
line-height: 29px;
|
font-size: 12px;
|
}
|
.item-field-label-div {
|
margin-left: 3px;
|
cursor: move;
|
background: #f4f6fc;
|
border: 1px solid #f4f6fc;
|
}
|
.item-field-label-div:hover {
|
border: 1px dashed #409eff;
|
}
|
.test-item-main-middle {
|
width: 67%;
|
padding-top: 24px;
|
border-left: 1px solid #e0e0e0;
|
border-right: 1px solid #e0e0e0;
|
}
|
.test-item-main-middle-header {
|
height: 36px;
|
border-bottom: 1px solid #e0e0e0;
|
text-align: right;
|
padding: 0px 20px;
|
}
|
.test-item-main-middle-body {
|
height: calc(100% - 36px);
|
padding: 0px 3px;
|
overflow: auto;
|
}
|
.test-item-row-div {
|
min-height: 60px;
|
}
|
.col-title {
|
display: flex;
|
justify-content: space-between;
|
height: 18px;
|
text-align: center;
|
}
|
.col-title >>> div {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
.test-item-main-right {
|
width: 14%;
|
padding-top: 24px;
|
}
|
.test-item-main-right-header {
|
height: 36px;
|
border-bottom: 1px solid #e0e0e0;
|
text-align: center;
|
line-height: 36px;
|
font-size: 15px;
|
}
|
.test-item-main-right-body {
|
}
|
.test-item-main-right-body >>> span {
|
width: 40px;
|
font-size: 13px;
|
line-height: 32px;
|
}
|
.test-item-main-right-body >>> .el-input {
|
width: calc(100% - 40px);
|
}
|
.test-item-main-right-body-title {
|
display: flex;
|
margin-top: 10px;
|
}
|
.test-item-main-right-body-width {
|
display: flex;
|
margin-top: 10px;
|
}
|
.group-title {
|
height: 30px;
|
}
|
.group-item {
|
border: 1px dashed #ccc;
|
}
|
.col-remark {
|
border-top: 1px solid #ccc;
|
height: 16px;
|
font-size: 12px;
|
text-align: center;
|
}
|
.item-input >>> input {
|
height: 28px;
|
}
|
.selected-item {
|
background: yellow !important;
|
}
|
</style>
|
<script>
|
import previewLayout from '@/views/quality/testitemlayout/preview-layout.vue'
|
import { getElPosition } from '@/util/plugin/dragAndDropFunc.js'
|
export default {
|
components: {
|
previewLayout
|
},
|
data() {
|
return {
|
checked: false,
|
checkItems: [
|
{
|
id: 1,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)1',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '1'
|
},
|
{
|
id: 2,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)2',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '2'
|
},
|
{
|
id: 3,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)3',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '3'
|
},
|
{
|
id: 4,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)4',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '4'
|
},
|
{
|
id: 5,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)5',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '5'
|
},
|
{
|
id: 6,
|
name: '铜带绕包—绝缘屏蔽线芯标称外径(陆缆)6',
|
remark: '要求范围:0.3-0.5',
|
itemNo: '6'
|
},
|
{ id: 7, name: '长度', remark: '要求范围:0.3-0.5', itemNo: '7' },
|
{ id: 8, name: '半径', remark: '要求范围:0.3-0.5', itemNo: '8' },
|
{ id: 9, name: '高度', remark: '要求范围:0.3-0.5', itemNo: '9' },
|
{ id: 10, name: '直径', remark: '要求范围:0.3-0.5', itemNo: '10' }
|
],
|
hasLayOutCheckItems: [],
|
layOutItems: [],
|
lastRowRef: null,
|
lastColRef: null,
|
inputVal: '',
|
inputVal1: '',
|
widthNum: 3,
|
itemTitle: null,
|
currUniqueId: null,
|
currColType: null,
|
currClickItem: null,
|
layOutJson: [],
|
showPreviewLayout: false
|
}
|
},
|
directives: {
|
layoutdrag: {
|
bind: function(el, binding, vnode) {
|
el.onmousedown = (e) => {
|
// 获取鼠标点击元素的文本内容
|
const elContent = el.innerText
|
// 获取鼠标点击元素的id,不同的belongDiv,对应的id组成不一样
|
const elId = el.id
|
// 是否允许拖动标识
|
let permitDrag = true
|
// 当前元素相对整个页面(除浏览器头部的位置)
|
const eleX = getElPosition(el).left
|
const eleY = getElPosition(el).top
|
// 鼠标点击元素所属的table
|
const belongDiv = binding.value.belongDiv
|
// 所属table的滚动偏移量
|
const scrollDistance = binding.value.getScrollDistance(belongDiv)
|
// 鼠标相对整个页面(除浏览器头部的位置),是e.clientX、e.clientY
|
// 鼠标与当前元素之间的位置差,是disX、disY
|
const disX = e.clientX - (eleX - scrollDistance.scrollX)
|
const disY = e.clientY - (eleY - scrollDistance.scrollY)
|
// 获取可拖动模块DIV的原始位置相对于整个页面(除浏览器头部的位置)
|
const moveBlock = binding.value.getInitMoveBlock()
|
const moveBlockX = moveBlock.moveBlockX
|
const moveBlockY = moveBlock.moveBlockY
|
// 设定拖拽模块的位置,使拖拽模块的位置,定位到鼠标点击的元素位置。(拖拽模块的top、left属性,是相对于最近一个父亲定位元素的距离)
|
binding.value.setMoveBlock(
|
eleX - moveBlockX - scrollDistance.scrollX,
|
eleY - moveBlockY - scrollDistance.scrollY,
|
elContent,
|
el.offsetWidth,
|
el.offsetHeight,
|
'move'
|
)
|
if (
|
belongDiv === 'itemTitleDiv' ||
|
belongDiv === 'groupTitleDiv' ||
|
belongDiv === 'groupItemTitleDiv'
|
) {
|
const uniqueId = binding.value.uniqueId
|
const colType = binding.value.colType
|
binding.value.itemClick(uniqueId, colType)
|
}
|
document.onmousemove = (e) => {
|
if (permitDrag) {
|
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
|
const event = e || window.event
|
|
let left = event.clientX - disX
|
let top = event.clientY - disY
|
// 限制左边距
|
if (left <= moveBlockX) {
|
left = moveBlockX
|
}
|
// 限制上边距
|
if (top < moveBlockY) {
|
top = moveBlockY
|
}
|
// 限制右边距
|
if (left > document.body.offsetWidth - el.offsetWidth) {
|
left = document.body.offsetWidth - el.offsetWidth
|
}
|
// 限制下边距
|
if (top > document.body.offsetHeight - el.offsetHeight) {
|
top = document.body.offsetHeight - el.offsetHeight
|
}
|
// 鼠标移动过程中,实时改变拖拽模块的位置,实现拖动效果。(拖拽模块的top、left属性,是相对于最近一个父亲定位元素的距离)
|
binding.value.setMoveBlock(
|
left - moveBlockX,
|
top - moveBlockY,
|
elContent,
|
null,
|
null,
|
null
|
)
|
// 寻找符合要求的检测项位置,即是拿当前鼠标光标的位置跟布局div中的检测项位置进行匹配。(此处是用鼠标光标的位置去对比匹配,而不是拖拽模块的位置)
|
binding.value.findAppropriatePosition(
|
event.clientX,
|
event.clientY,
|
belongDiv
|
)
|
}
|
}
|
document.onmouseup = (e) => {
|
if (permitDrag) {
|
const event = e || window.event
|
// 鼠标放开后,进行布局
|
binding.value.setAppropriatePosition(
|
event.clientX,
|
event.clientY,
|
elId,
|
belongDiv
|
)
|
// 布局完成后,对拖拽模块进行初始化,使其回到默认初始位置
|
binding.value.initMoveBlock()
|
permitDrag = false
|
document.onmousemove = null
|
document.onmouseup = null
|
}
|
}
|
}
|
}
|
}
|
},
|
created() {
|
const currTime = new Date().getTime()
|
// const currTime1 = new Date().getTime()
|
// const currTime2 = new Date().getTime()
|
const layOutItem = {
|
id: null,
|
label: '',
|
uniqueId: currTime,
|
minHeight: 60,
|
cols: [
|
/* {
|
id: null,
|
uniqueId: currTime1,
|
label: '分组',
|
span: 24,
|
type: 'group',
|
children: [
|
{
|
id: null,
|
label: '',
|
uniqueId: currTime,
|
cols: [
|
{
|
id: null,
|
uniqueId: currTime2,
|
label: '',
|
span: 4
|
}
|
]
|
}
|
]
|
} */
|
]
|
}
|
this.layOutItems.push(layOutItem)
|
},
|
methods: {
|
// 获取div滚动偏移量,div出现滚动条时,滚动条滚动之后会有位置偏移,滚动条不滚动,偏移为0,无滚动条时,偏移为0
|
getScrollDistance(belongDiv) {
|
// 若belongDiv为itemTitleDiv groupTitleDiv groupItemTitleDiv layOutContentDiv,则都以layOutContentDiv来计算
|
let scrollPosition
|
if (
|
belongDiv === 'itemTitleDiv' ||
|
belongDiv === 'groupTitleDiv' ||
|
belongDiv === 'groupItemTitleDiv' ||
|
belongDiv === 'layOutContentDiv'
|
) {
|
scrollPosition = {
|
scrollX: this.$refs.layOutContentDiv.scrollLeft,
|
scrollY: this.$refs.layOutContentDiv.scrollTop
|
}
|
} else if (belongDiv === 'groupLayOutDiv') {
|
scrollPosition = {
|
scrollX: this.$refs.groupLayOutDiv.scrollLeft,
|
scrollY: this.$refs.groupLayOutDiv.scrollTop
|
}
|
} else if (belongDiv === 'itemLayOutDiv') {
|
scrollPosition = {
|
scrollX: this.$refs.itemLayOutDiv.scrollLeft,
|
scrollY: this.$refs.itemLayOutDiv.scrollTop
|
}
|
}
|
return scrollPosition
|
},
|
// 初始化可拖动块的样式
|
initMoveBlock() {
|
this.$refs.moveBlock.style.top = '0px'
|
this.$refs.moveBlock.style.left = '0px'
|
this.$refs.moveBlock.style.width = '0px'
|
this.$refs.moveBlock.style.height = '0px'
|
this.$refs.moveBlock.style.lineHeight = '0px'
|
this.$refs.moveBlock.style.border = '0px dashed #409eff'
|
this.$refs.moveBlock.innerText = ''
|
this.$refs.moveBlock.style.cursor = ''
|
},
|
// 获取可拖动块,相对于整个页面(除浏览器头部坐标)
|
getInitMoveBlock() {
|
return {
|
moveBlockX: getElPosition(this.$refs.moveBlock).left,
|
moveBlockY: getElPosition(this.$refs.moveBlock).top
|
}
|
},
|
// 设置可拖动块的样式
|
setMoveBlock(x, y, content, width, height, cursor) {
|
this.$refs.moveBlock.style.top = y + 'px'
|
this.$refs.moveBlock.style.left = x + 'px'
|
this.$refs.moveBlock.innerText = content
|
this.$refs.moveBlock.style.border = '1px dashed #409eff'
|
if (width != null) {
|
this.$refs.moveBlock.style.width = width + 'px'
|
}
|
if (height != null) {
|
this.$refs.moveBlock.style.height = height + 'px'
|
this.$refs.moveBlock.style.lineHeight = height + 'px'
|
}
|
if (cursor != null) {
|
this.$refs.moveBlock.style.cursor = cursor
|
}
|
},
|
// 先对行进行循环,再对行中的列进行循环。布局字段分组只能放在空行中,检测项字段无此限制。
|
findAppropriatePosition(x, y, belongDiv) {
|
let layOutItem
|
let rowRef
|
let elposition
|
if (this.lastRowRef != null && this.$refs[this.lastRowRef].length > 0) {
|
this.$refs[this.lastRowRef][0].style.borderLeft = '0px solid #409eff'
|
}
|
if (this.lastColRef != null && this.$refs[this.lastColRef].length > 0) {
|
this.$refs[this.lastColRef][0].style.borderRight = '0px solid #409eff'
|
}
|
|
// 获取layOutContentDiv滚动偏移量,layOutContentDiv出现滚动条时,滚动条滚动之后会有位置偏移,滚动条不滚动,偏移为0,无滚动条时,偏移为0
|
const personArrangeTableScrollPosition = this.getScrollDistance(
|
'layOutContentDiv'
|
)
|
// 布局字段分组的拖拽
|
if (belongDiv === 'groupLayOutDiv') {
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
if (layOutItem.cols.length <= 0) {
|
this.$refs[rowRef][0].style.borderLeft = '3px solid #409eff'
|
}
|
this.lastRowRef = rowRef
|
break
|
}
|
}
|
} else {
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
if (layOutItem.cols.length > 0) {
|
// 判断是否拖拽进分组控件,若是拖拽至分组控件,则需按分组的数据结构进行查找,通过第一层的cols中的type对象进行判断,group为分组控件、item为普通列
|
const cols = layOutItem.cols
|
let colRef
|
const col = cols[0]
|
if (col.type === 'group') {
|
// 分组控件中的行
|
const groupRows = col.children
|
let groupRow
|
for (let i = 0; i < groupRows.length; i++) {
|
groupRow = groupRows[i]
|
rowRef = 'body_row_' + groupRow.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
// 判断分组中的行,是否已存在检测项列
|
if (groupRow.cols.length > 0) {
|
const groupCols = groupRow.cols
|
let groupCol
|
for (let j = 0; j < groupCols.length; j++) {
|
colRef = 'body_col_' + groupCols[j].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
this.$refs[colRef][0].style.borderRight =
|
'3px solid #409eff'
|
this.lastColRef = colRef
|
}
|
}
|
} else {
|
this.$refs[rowRef][0].style.borderLeft =
|
'3px solid #409eff'
|
}
|
this.lastRowRef = rowRef
|
break
|
}
|
}
|
} else {
|
for (let i = 0; i < cols.length; i++) {
|
colRef = 'body_col_' + cols[i].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
this.$refs[colRef][0].style.borderRight =
|
'3px solid #409eff'
|
this.lastColRef = colRef
|
}
|
}
|
}
|
} else {
|
this.$refs[rowRef][0].style.borderLeft = '3px solid #409eff'
|
}
|
this.lastRowRef = rowRef
|
break
|
}
|
}
|
}
|
},
|
// 鼠标键松开弹起时,判断鼠标光标的位置,根据鼠标光标位置,进行布局
|
// 分情况进行布局,若是拖拽元素来自于itemLayOutDiv、groupLayOutDiv,则进行普通布局,即往layOutItems插入新增数据
|
// 若是拖拽元素来自于itemTitleDiv、groupTitleDiv、groupItemTitleDiv,则进行位置调整布局,即将layOutItems中的元素进行位置的调整。
|
// 根据uniqueId查询拖拽元素,并进行位置调整
|
setAppropriatePosition(x, y, elId, belongDiv) {
|
if (belongDiv === 'itemLayOutDiv' || belongDiv === 'groupLayOutDiv') {
|
this.generalLayout(x, y, elId, belongDiv)
|
} else {
|
this.positionAdjustmentLayout(x, y, elId, belongDiv)
|
}
|
},
|
// 普通布局
|
generalLayout(x, y, elId, belongDiv) {
|
let layOutItem
|
let rowRef
|
let elposition
|
const checkItem = this.checkItems.find((item) => {
|
return item.id == elId
|
})
|
|
// 获取layOutContentDiv滚动偏移量,layOutContentDiv出现滚动条时,滚动条滚动之后会有位置偏移,滚动条不滚动,偏移为0,无滚动条时,偏移为0
|
const personArrangeTableScrollPosition = this.getScrollDistance(
|
'layOutContentDiv'
|
)
|
// 布局字段分组的拖拽定位
|
if (belongDiv === 'groupLayOutDiv') {
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
const cols = layOutItem.cols
|
if (cols.length <= 0) {
|
// 当前行 为空行,往里面直接插入分组,并且新增一行
|
const groupUniqueId = new Date().getTime()
|
layOutItem.minHeight = 100
|
cols.push({
|
id: null,
|
uniqueId: groupUniqueId,
|
label: '分组',
|
span: 24,
|
isSelect: false,
|
type: 'group',
|
children: [
|
{
|
id: null,
|
label: '',
|
uniqueId: groupUniqueId + 1,
|
cols: []
|
}
|
]
|
})
|
const layOut = {
|
id: null,
|
label: '',
|
uniqueId: groupUniqueId + 2,
|
minHeight: 60,
|
cols: []
|
}
|
this.layOutItems.push(layOut)
|
}
|
break
|
}
|
}
|
} else {
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
const cols = layOutItem.cols
|
if (cols.length > 0) {
|
let colRef
|
// 判断是否拖拽进分组控件,若是拖拽至分组控件,则需按分组的数据结构进行项增加,通过第一层的cols中的type对象进行判断,group为分组控件、item为普通列
|
const col = cols[0]
|
if (col.type === 'group') {
|
// 分组控件中的行
|
const groupRows = col.children
|
let groupRow
|
for (let i = 0; i < groupRows.length; i++) {
|
groupRow = groupRows[i]
|
rowRef = 'body_row_' + groupRow.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
// 判断分组中的行,是否已存在检测项列
|
if (groupRow.cols.length > 0) {
|
const groupCols = groupRow.cols
|
for (let j = 0; j < groupCols.length; j++) {
|
colRef = 'body_col_' + groupCols[j].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
// 删除checkItems中的checkItem,复制到hasLayOutCheckItems中
|
this.hasLayOutCheckItems.push(checkItem)
|
const checkItemIndex = this.checkItems.indexOf(
|
checkItem
|
)
|
this.checkItems.splice(checkItemIndex, 1)
|
// 在此检测项后面,新增检测项
|
const colUniqueId = new Date().getTime()
|
groupCols.splice(j + 1, 0, {
|
id: null,
|
uniqueId: colUniqueId,
|
label: checkItem.name,
|
type: '',
|
remark: checkItem.remark,
|
span: 4,
|
isSelect: false,
|
itemNo: checkItem.itemNo
|
})
|
break
|
}
|
}
|
} else {
|
// 删除checkItems中的checkItem,复制到hasLayOutCheckItems中
|
this.hasLayOutCheckItems.push(checkItem)
|
const checkItemIndex = this.checkItems.indexOf(checkItem)
|
this.checkItems.splice(checkItemIndex, 1)
|
// 当前行 为空行,往里面直接插入检测项,并且新增一行
|
const colUniqueId = new Date().getTime()
|
layOutItem.minHeight = layOutItem.minHeight + 60
|
groupRow.cols.push({
|
id: null,
|
uniqueId: colUniqueId,
|
label: checkItem.name,
|
type: '',
|
remark: checkItem.remark,
|
span: 4,
|
isSelect: false,
|
itemNo: checkItem.itemNo
|
})
|
|
groupRows.push({
|
id: null,
|
label: '',
|
uniqueId: colUniqueId + 1,
|
cols: []
|
})
|
}
|
break
|
}
|
}
|
} else {
|
for (let i = 0; i < cols.length; i++) {
|
colRef = 'body_col_' + cols[i].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
// 删除checkItems中的checkItem,复制到hasLayOutCheckItems中
|
this.hasLayOutCheckItems.push(checkItem)
|
const checkItemIndex = this.checkItems.indexOf(checkItem)
|
this.checkItems.splice(checkItemIndex, 1)
|
// 在此检测项后面,新增检测项
|
const colUniqueId = new Date().getTime()
|
cols.splice(i + 1, 0, {
|
id: null,
|
uniqueId: colUniqueId,
|
label: checkItem.name,
|
type: 'item',
|
remark: checkItem.remark,
|
span: 4,
|
isSelect: false,
|
itemNo: checkItem.itemNo
|
})
|
break
|
}
|
}
|
}
|
} else {
|
// 删除checkItems中的checkItem,复制到hasLayOutCheckItems中
|
this.hasLayOutCheckItems.push(checkItem)
|
const checkItemIndex = this.checkItems.indexOf(checkItem)
|
this.checkItems.splice(checkItemIndex, 1)
|
// 当前行 为空行,往里面直接插入检测项,并且新增一行
|
const colUniqueId = new Date().getTime()
|
cols.push({
|
id: null,
|
uniqueId: colUniqueId,
|
label: checkItem.name,
|
type: 'item',
|
remark: checkItem.remark,
|
span: 4,
|
isSelect: false,
|
itemNo: checkItem.itemNo
|
})
|
|
const layOut = {
|
id: null,
|
label: '',
|
uniqueId: colUniqueId + 1,
|
minHeight: 60,
|
cols: []
|
}
|
this.layOutItems.push(layOut)
|
}
|
break
|
}
|
}
|
}
|
},
|
// 位置调整布局
|
positionAdjustmentLayout(x, y, elId, belongDiv) {
|
// x、y为鼠标的光标位置
|
// 参数中belongDiv值有两种:itemTitleDiv、groupTitleDiv、groupItemTitleDiv
|
// elId是拖拽元素的uniqueId,即为layOutItems中的uniqueId
|
let layOutItem
|
let rowRef
|
let elposition
|
|
// 获取layOutContentDiv滚动偏移量,layOutContentDiv出现滚动条时,滚动条滚动之后会有位置偏移,滚动条不滚动,偏移为0,无滚动条时,偏移为0
|
const personArrangeTableScrollPosition = this.getScrollDistance(
|
'layOutContentDiv'
|
)
|
// 当前拖拽的项,分两种情况去检索,itemTitleDiv、groupTitleDiv一组,groupItemTitleDiv一组
|
// 检索出currItem
|
const currItem = this.getCurrItem(belongDiv, elId)
|
// 拖拽项为groupTitleDiv时,groupTitleDiv是分组,不能被拖拽至另一个分组,且必须占一行。若被拖拽至的行已有项,则放入下一行(新增行),若被拖拽至的行是空行,则直接放入该行
|
if (belongDiv === 'groupTitleDiv') {
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
// 删除原有行
|
let rowNum
|
rowNum = this.getRowNum(currItem, belongDiv)
|
if (rowNum !== k) {
|
this.layOutItems.splice(rowNum, 1)
|
const cols = layOutItem.cols
|
if (cols.length <= 0) {
|
// 被拖拽至的行是空行,则直接放入该行,并且新增一行
|
const groupUniqueId = new Date().getTime()
|
layOutItem.minHeight = 40 + currItem.children.length * 60
|
cols.push(currItem)
|
const layOut = {
|
id: null,
|
label: '',
|
uniqueId: groupUniqueId,
|
minHeight: 60,
|
cols: []
|
}
|
this.layOutItems.push(layOut)
|
} else {
|
// 被拖拽至的行已有项,则放入下一行(新增行)
|
const groupUniqueId = new Date().getTime()
|
rowNum = this.layOutItems.indexOf(layOutItem)
|
this.layOutItems.splice(rowNum + 1, 0, {
|
id: null,
|
label: '',
|
uniqueId: groupUniqueId,
|
minHeight: 40 + currItem.children.length * 60,
|
cols: [currItem]
|
})
|
}
|
}
|
break
|
}
|
}
|
} else {
|
// 拖拽项为itemTitleDiv、groupItemTitleDiv时,若被拖拽至的行已有项,则插入在该项后,若被拖拽至的行是空行,则直接放入该行
|
for (let k = 0; k < this.layOutItems.length; k++) {
|
layOutItem = this.layOutItems[k]
|
rowRef = 'body_row_' + layOutItem.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x > elposition.left - personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y > elposition.top - personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
const cols = layOutItem.cols
|
if (cols.length > 0) {
|
let colRef
|
// 判断是否拖拽进分组控件,若是拖拽至分组控件,则需按分组的数据结构进行项增加,通过第一层的cols中的type对象进行判断,group为分组控件、item为普通列
|
const col = cols[0]
|
if (col.type === 'group') {
|
// 分组控件中的行
|
const groupRows = col.children
|
let groupRow
|
for (let i = 0; i < groupRows.length; i++) {
|
groupRow = groupRows[i]
|
rowRef = 'body_row_' + groupRow.uniqueId
|
elposition = getElPosition(this.$refs[rowRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[rowRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[rowRef][0].offsetHeight
|
) {
|
// 判断分组中的行,是否已存在检测项列
|
if (groupRow.cols.length > 0) {
|
const groupCols = groupRow.cols
|
let groupCol
|
for (let j = 0; j < groupCols.length; j++) {
|
groupCol = groupCols[j]
|
colRef = 'body_col_' + groupCols[j].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
// 删除拖拽的项,若有必要,需删除所属行,分两种类型itemTitleDiv、groupItemTitleDiv,itemTitleDiv为layOutItems外层的col项,groupItemTitleDiv为layOutItems内层的col项
|
const currRowInfo = this.getRow(belongDiv, elId)
|
const currRow = currRowInfo.currRow
|
const rowNum = this.layOutItems.indexOf(currRow)
|
if (belongDiv === 'itemTitleDiv') {
|
if (currRow.cols.length === 1) {
|
// 项所属行内只有该项,则直接删除该行
|
this.layOutItems.splice(rowNum, 1)
|
} else {
|
const currItemNum = currRow.cols.indexOf(currItem)
|
currRow.cols.splice(currItemNum, 1)
|
}
|
// 在此检测项后面,新增检测项
|
currItem.type = ''
|
groupCols.splice(j + 1, 0, currItem)
|
} else {
|
const currChild = currRowInfo.currChild
|
const children = this.layOutItems[rowNum].cols[0]
|
.children
|
const childNum = children.indexOf(currChild)
|
if (children.length > 1) {
|
// 判断项是否是分组内,还是不同分组
|
if (rowNum === k) {
|
// 项在分组内
|
// 项属于分组行,判断是否是分组内跨行拖拽
|
if (i !== childNum) {
|
// 跨行拖拽,项属于分组行,且有多行,若行内只有该项,则直接删除该行,若有多项,则直接删除该项
|
if (currChild.cols.length === 1) {
|
children.splice(childNum, 1)
|
currRow.minHeight = currRow.minHeight - 60
|
} else {
|
const currItemNum = currChild.cols.indexOf(
|
currItem
|
)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
// 在此检测项后面,新增检测项
|
groupCols.splice(j + 1, 0, currItem)
|
} else {
|
// 行内拖拽,项属于分组行,且有多行,若拖拽项未拖动或者未拖动出自身范围,则不操作,若拖拽项拖拽至其他项目范围,则删除该项
|
const currItemNum = currChild.cols.indexOf(
|
currItem
|
)
|
if (j !== currItemNum) {
|
currChild.cols.splice(currItemNum, 1)
|
// 因删除了项,所以groupCols中项位置发生变化,需重新获取groupCol的位置
|
const groupColNum = groupCols.indexOf(
|
groupCol
|
)
|
groupCols.splice(
|
groupColNum + 1,
|
0,
|
currItem
|
)
|
}
|
}
|
} else {
|
// 项在另一个分组
|
if (currChild.cols.length === 1) {
|
children.splice(childNum, 1)
|
currRow.minHeight = currRow.minHeight - 60
|
} else {
|
const currItemNum = currChild.cols.indexOf(
|
currItem
|
)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
// 在此检测项后面,新增检测项
|
groupCols.splice(j + 1, 0, currItem)
|
}
|
}
|
}
|
break
|
}
|
}
|
} else {
|
// 删除拖拽的项,若有必要,需删除所属行,分两种类型itemTitleDiv、groupItemTitleDiv,itemTitleDiv为layOutItems外层的col项,groupItemTitleDiv为layOutItems内层的col项
|
const currRowInfo = this.getRow(belongDiv, elId)
|
const currRow = currRowInfo.currRow
|
const rowNum = this.layOutItems.indexOf(currRow)
|
if (belongDiv === 'itemTitleDiv') {
|
if (currRow.cols.length === 1) {
|
// 项所属行内只有该项,则直接删除该行
|
this.layOutItems.splice(rowNum, 1)
|
} else {
|
const currItemNum = currRow.cols.indexOf(currItem)
|
currRow.cols.splice(currItemNum, 1)
|
}
|
} else {
|
const currChild = currRowInfo.currChild
|
const children = this.layOutItems[rowNum].cols[0]
|
.children
|
if (children.length > 1) {
|
// 项属于分组行,且有多行,若行内只有该项,则直接删除该行,若有多项,则直接删除该项
|
if (currChild.cols.length === 1) {
|
const childNum = children.indexOf(currChild)
|
children.splice(childNum, 1)
|
currRow.minHeight = currRow.minHeight - 60
|
} else {
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
} else {
|
// 项属于分组行,且只有一行,行不能删除,只删除项
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
}
|
// 当前行 为空行,往里面直接插入检测项,并且新增一行
|
const colUniqueId = new Date().getTime()
|
layOutItem.minHeight = layOutItem.minHeight + 60
|
if (belongDiv === 'itemTitleDiv') {
|
currItem.type = ''
|
}
|
groupRow.cols.push(currItem)
|
|
groupRows.push({
|
id: null,
|
label: '',
|
uniqueId: colUniqueId,
|
cols: []
|
})
|
}
|
break
|
}
|
}
|
} else {
|
let itemCol
|
for (let i = 0; i < cols.length; i++) {
|
itemCol = cols[i]
|
colRef = 'body_col_' + cols[i].uniqueId
|
elposition = getElPosition(this.$refs[colRef][0])
|
if (
|
x >
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX &&
|
x <
|
elposition.left -
|
personArrangeTableScrollPosition.scrollX +
|
this.$refs[colRef][0].offsetWidth &&
|
y >
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY &&
|
y <
|
elposition.top -
|
personArrangeTableScrollPosition.scrollY +
|
this.$refs[colRef][0].offsetHeight
|
) {
|
// 删除拖拽的项,若有必要,需删除所属行,分两种类型itemTitleDiv、groupItemTitleDiv,itemTitleDiv为layOutItems外层的col项,groupItemTitleDiv为layOutItems内层的col项
|
const currRowInfo = this.getRow(belongDiv, elId)
|
const currRow = currRowInfo.currRow
|
const rowNum = this.layOutItems.indexOf(currRow)
|
if (belongDiv === 'itemTitleDiv') {
|
// 需考虑拖拽是否跨行,
|
if (rowNum !== k) {
|
// 此时跨行,是跨行拖拽
|
if (currRow.cols.length === 1) {
|
// 项所属行内只有该项,则直接删除该行
|
this.layOutItems.splice(rowNum, 1)
|
} else {
|
// 项所属行内有多项,则直接删除该项
|
const currItemNum = currRow.cols.indexOf(currItem)
|
currRow.cols.splice(currItemNum, 1)
|
}
|
// 在此检测项后面,新增检测项
|
cols.splice(i + 1, 0, currItem)
|
} else {
|
// 此时未跨行,是行内拖拽
|
// 若拖拽项未拖动或者未拖动出自身范围,则不操作,若拖拽项拖拽至其他项目范围,则删除该项
|
const currItemNum = currRow.cols.indexOf(currItem)
|
if (i !== currItemNum) {
|
currRow.cols.splice(currItemNum, 1)
|
// 因删除了项,所以cols中项位置发生变化,需重新获取itemCol的位置
|
const itemColNum = cols.indexOf(itemCol)
|
cols.splice(itemColNum + 1, 0, currItem)
|
}
|
}
|
} else {
|
const currChild = currRowInfo.currChild
|
const children = this.layOutItems[rowNum].cols[0].children
|
if (children.length > 1) {
|
// 项属于分组行,且有多行,若行内只有该项,则直接删除该行,若有多项,则直接删除该项
|
if (currChild.cols.length === 1) {
|
const childNum = children.indexOf(currChild)
|
children.splice(childNum, 1)
|
currRow.minHeight = currRow.minHeight - 60
|
} else {
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
} else {
|
// 项属于分组行,且只有一行,行不能删除,只删除项
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
// 在此检测项后面,新增检测项
|
currItem.type = 'item'
|
cols.splice(i + 1, 0, currItem)
|
}
|
break
|
}
|
}
|
}
|
} else {
|
// 删除拖拽的项,若有必要,需删除所属行,分两种类型itemTitleDiv、groupItemTitleDiv,itemTitleDiv为layOutItems外层的col项,groupItemTitleDiv为layOutItems内层的col项
|
const currRowInfo = this.getRow(belongDiv, elId)
|
const currRow = currRowInfo.currRow
|
const rowNum = this.layOutItems.indexOf(currRow)
|
if (rowNum !== k) {
|
if (belongDiv === 'itemTitleDiv') {
|
if (currRow.cols.length === 1) {
|
// 项所属行内只有该项,则直接删除该行
|
this.layOutItems.splice(rowNum, 1)
|
} else {
|
const currItemNum = currRow.cols.indexOf(currItem)
|
currRow.cols.splice(currItemNum, 1)
|
}
|
} else {
|
const currChild = currRowInfo.currChild
|
const children = this.layOutItems[rowNum].cols[0].children
|
if (children.length > 1) {
|
// 项属于分组行,且有多行,若行内只有该项,则直接删除该行,若有多项,则直接删除该项
|
if (currChild.cols.length === 1) {
|
const childNum = children.indexOf(currChild)
|
children.splice(childNum, 1)
|
currRow.minHeight = currRow.minHeight - 60
|
} else {
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
} else {
|
// 项属于分组行,且只有一行,行不能删除,只删除项
|
const currItemNum = currChild.cols.indexOf(currItem)
|
currChild.cols.splice(currItemNum, 1)
|
}
|
}
|
// 当前行 为空行,往里面直接插入检测项,并且新增一行
|
const colUniqueId = new Date().getTime()
|
if (belongDiv === 'groupItemTitleDiv') {
|
currItem.type = 'item'
|
}
|
cols.push(currItem)
|
|
const layOut = {
|
id: null,
|
label: '',
|
uniqueId: colUniqueId,
|
minHeight: 60,
|
cols: []
|
}
|
this.layOutItems.push(layOut)
|
}
|
}
|
break
|
}
|
}
|
}
|
},
|
// 获取当前项所属的行,itemTitleDiv、groupItemTitleDiv所属行的数据结构不一样,itemTitleDiv是外层行,groupItemTitleDiv是内层行
|
getRow(belongDiv, elId) {
|
let currItem
|
let currRow
|
let currChild
|
if (belongDiv === 'itemTitleDiv') {
|
let layOut
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOut = this.layOutItems[i]
|
currItem = layOut.cols.find((item) => {
|
return item.uniqueId == elId
|
})
|
if (currItem) {
|
currRow = layOut
|
break
|
}
|
}
|
} else {
|
let layOut
|
let childs
|
let child
|
let childItem
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOut = this.layOutItems[i]
|
if (layOut.cols.length > 0) {
|
if (layOut.cols[0].children) {
|
childs = layOut.cols[0].children
|
for (let j = 0; j < childs.length; j++) {
|
child = childs[j]
|
childItem = child.cols.find((item) => {
|
return item.uniqueId == elId
|
})
|
if (childItem) {
|
currRow = layOut
|
currChild = child
|
}
|
}
|
}
|
}
|
}
|
}
|
return { currRow: currRow, currChild: currChild }
|
},
|
// 获取当前项所属的行号
|
getRowNum(currItem, belongDiv) {
|
let rowNum
|
if (belongDiv === 'groupTitleDiv') {
|
let layOut
|
let layOutCol
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOut = this.layOutItems[i]
|
layOutCol = layOut.cols.find((item) => {
|
return item.uniqueId === currItem.uniqueId
|
})
|
if (layOutCol) {
|
rowNum = i
|
break
|
}
|
}
|
}
|
return rowNum
|
},
|
// 获取当前拖拽的项
|
getCurrItem(belongDiv, elId) {
|
let currItem
|
if (belongDiv === 'itemTitleDiv' || belongDiv === 'groupTitleDiv') {
|
let layOut
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOut = this.layOutItems[i]
|
currItem = layOut.cols.find((item) => {
|
return item.uniqueId == elId
|
})
|
if (currItem) {
|
break
|
}
|
}
|
} else {
|
let layOut
|
let childs
|
let child
|
let childItem
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOut = this.layOutItems[i]
|
if (layOut.cols.length > 0) {
|
if (layOut.cols[0].children) {
|
childs = layOut.cols[0].children
|
for (let j = 0; j < childs.length; j++) {
|
child = childs[j]
|
childItem = child.cols.find((item) => {
|
return item.uniqueId == elId
|
})
|
if (childItem) {
|
currItem = childItem
|
}
|
}
|
}
|
}
|
}
|
}
|
return currItem
|
},
|
// 点击某个检测项或者分组,触发
|
itemClick(uniqueId, colType) {
|
this.currUniqueId = uniqueId
|
this.currColType = colType
|
if (this.currClickItem != null) {
|
this.currClickItem.isSelect = false
|
this.currClickItem = null
|
}
|
let clickItem
|
if (colType === 'firstCol') {
|
// 点击的是第一层的col项
|
let layOutItem
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOutItem = this.layOutItems[i]
|
clickItem = layOutItem.cols.find((item) => {
|
return item.uniqueId === uniqueId
|
})
|
if (clickItem) {
|
this.currClickItem = clickItem
|
break
|
}
|
}
|
} else {
|
// 点击的是第二层的col项
|
let layOutItem
|
let childs
|
let child
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOutItem = this.layOutItems[i]
|
if (layOutItem.cols.length > 0) {
|
if (layOutItem.cols[0].children) {
|
childs = layOutItem.cols[0].children
|
for (let j = 0; j < childs.length; j++) {
|
child = childs[j]
|
clickItem = child.cols.find((item) => {
|
return item.uniqueId === uniqueId
|
})
|
if (clickItem) {
|
this.currClickItem = clickItem
|
}
|
}
|
}
|
}
|
}
|
}
|
if (this.currClickItem != null) {
|
this.currClickItem.isSelect = true
|
this.widthNum = this.currClickItem.span
|
this.itemTitle = this.currClickItem.label
|
}
|
},
|
// 标题改变,更新项标题
|
titleChange() {
|
if (this.currClickItem != null) {
|
this.currClickItem.label = this.itemTitle
|
}
|
},
|
// 宽度改变,更新项宽度
|
widthChange(value) {
|
if (this.currClickItem != null) {
|
this.currClickItem.span = this.widthNum
|
}
|
},
|
// 删除已布局的项
|
delItem(
|
type,
|
firstRowIndex,
|
firstColIndex,
|
secondRowIndex,
|
secondColIndex
|
) {
|
// type删除项类型,firstRowIndex外层行号,
|
// 需将hasLayOutCheckItems中项移至checkItems
|
// 删除普通项时type='0',若所在行存在多项,则只需删除layOutItem.cols中的该项,若所在行只有该项,则需删除整行layOutItem
|
// 删除分组中普通项时type='1',若所在行存在多项,则只需删除child.cols中的该项,若所在行只有该项,则需删除整行child
|
// 删除分组时type='2',直接删除整行layOutItem
|
if (type === '0') {
|
const cols = this.layOutItems[firstRowIndex].cols
|
const col = cols[firstColIndex]
|
const checkItem = this.hasLayOutCheckItems.find((item) => {
|
return item.itemNo === col.itemNo
|
})
|
if (checkItem) {
|
this.checkItems.push(checkItem)
|
const hasLayOutCheckItemIndex = this.hasLayOutCheckItems.indexOf(
|
checkItem
|
)
|
this.hasLayOutCheckItems.splice(hasLayOutCheckItemIndex, 1)
|
}
|
if (cols.length > 1) {
|
cols.splice(firstColIndex, 1)
|
} else {
|
this.layOutItems.splice(firstRowIndex, 1)
|
}
|
} else if (type === '1') {
|
const childs = this.layOutItems[firstRowIndex].cols[firstColIndex]
|
.children
|
const childCols = childs[secondRowIndex].cols
|
const childCol = childCols[secondColIndex]
|
const checkItem = this.hasLayOutCheckItems.find((item) => {
|
return item.itemNo === childCol.itemNo
|
})
|
if (checkItem) {
|
this.checkItems.push(checkItem)
|
const hasLayOutCheckItemIndex = this.hasLayOutCheckItems.indexOf(
|
checkItem
|
)
|
this.hasLayOutCheckItems.splice(hasLayOutCheckItemIndex, 1)
|
}
|
if (childCols.length > 1) {
|
childCols.splice(secondColIndex, 1)
|
} else {
|
childs.splice(secondRowIndex, 1)
|
this.layOutItems[firstRowIndex].minHeight =
|
this.layOutItems[firstRowIndex].minHeight - 60
|
}
|
} else if (type === '2') {
|
// 判断分组中是否存在项,若存在项,则需将hasLayOutCheckItems中项移至checkItems
|
const childs = this.layOutItems[firstRowIndex].cols[firstColIndex]
|
.children
|
let child
|
let cols
|
for (let i = 0; i < childs.length; i++) {
|
child = childs[i]
|
cols = child.cols
|
if (cols.length > 0) {
|
let col
|
for (let j = 0; j < cols.length; j++) {
|
col = cols[j]
|
const checkItem = this.hasLayOutCheckItems.find((item) => {
|
return item.itemNo === col.itemNo
|
})
|
if (checkItem) {
|
this.checkItems.push(checkItem)
|
const hasLayOutCheckItemIndex = this.hasLayOutCheckItems.indexOf(
|
checkItem
|
)
|
this.hasLayOutCheckItems.splice(hasLayOutCheckItemIndex, 1)
|
}
|
}
|
}
|
}
|
this.layOutItems.splice(firstRowIndex, 1)
|
}
|
// 置空当前的点击项
|
this.currClickItem = null
|
},
|
// 提交生成的布局json
|
submitJson() {
|
console.log('this.layOutItems', this.layOutItems)
|
},
|
// 弹出布局结果预览窗口
|
previewLayOut() {
|
this.showPreviewLayout = true
|
this.layOutJson = []
|
// 排除掉cols为空的行(一层和二层)
|
let layOutItem
|
let firstCols
|
let firstCol
|
let childs
|
let child
|
for (let i = 0; i < this.layOutItems.length; i++) {
|
layOutItem = this.layOutItems[i]
|
firstCols = layOutItem.cols
|
if (firstCols.length > 0) {
|
// 判断是是否为分组
|
firstCol = firstCols[0]
|
if (firstCol.type === 'item') {
|
// 普通列
|
this.layOutJson.push(layOutItem)
|
} else {
|
const copyChildren = []
|
const copyLayOutItem = {
|
id: layOutItem.id,
|
label: layOutItem.label,
|
uniqueId: layOutItem.uniqueId,
|
minHeight: layOutItem.minHeight,
|
cols: [
|
{
|
id: firstCol.id,
|
uniqueId: firstCol.uniqueId,
|
label: firstCol.label,
|
span: firstCol.span,
|
isSelect: firstCol.isSelect,
|
type: firstCol.type,
|
children: copyChildren
|
}
|
]
|
}
|
// 分组列
|
childs = firstCol.children
|
if (childs.length > 0) {
|
for (let j = 0; j < childs.length; j++) {
|
child = childs[j]
|
if (child.cols.length > 0) {
|
copyChildren.push(child)
|
}
|
}
|
}
|
if (copyChildren.length > 0) {
|
copyLayOutItem.minHeight = 40 + copyChildren.length * 60
|
this.layOutJson.push(copyLayOutItem)
|
}
|
}
|
}
|
}
|
},
|
// 清空布局,相当于页面初始化
|
cleanLayOut() {
|
const currTime = new Date().getTime()
|
// 需调用后台重新加载数据
|
this.checkItems = []
|
this.hasLayOutCheckItems = []
|
this.layOutItems = []
|
const layOutItem = {
|
id: null,
|
label: '',
|
uniqueId: currTime,
|
minHeight: 60,
|
cols: []
|
}
|
this.layOutItems.push(layOutItem)
|
this.lastRowRef = null
|
this.lastColRef = null
|
this.inputVal = ''
|
this.inputVal1 = ''
|
this.widthNum = 3
|
this.itemTitle = null
|
this.currUniqueId = null
|
this.currColType = null
|
this.currClickItem = null
|
}
|
}
|
}
|
</script>
|