<template> <div class="element-tier-edit"> <div class="tier-menu"> <div v-for="(column, cindex) in curPage.columns" :key="column.id" :class="['tier-menu-item', { 'is-active': column.id === curColumn.id }]" @click="selectColumn(column)" > 栏{{ cindex + 1 }} </div> </div> <div ref="TierList" class="tier-list" @drop.prevent="dropInnerElement" @dragover.prevent="dragOver($event)" @dragleave.prevent > <div v-for="element in curColumn.elements" :key="element.id" :class="[ 'tier-item', { 'after-drop': element.id === curDropElementId && isDragDown, 'before-drop': element.id === curDropElementId && !isDragDown, }, ]" :id="`tier-${element.id}`" draggable="true" @dragstart="($event) => dragStart($event, element)" @dragend.prevent="dragEnd" @click="selectElement(element)" > <div :class="[ 'tier-item-cont', { 'is-active': curElement.id === element.id, }, ]" > {{ element.desc }} </div> <!-- <div class="tier-item-cont">{{ element.zindex }}:{{ element.id }}</div> --> </div> </div> </div> </template> <script> import { mapState, mapMutations, mapActions } from "vuex"; export default { name: "element-tier-edit", data() { return { curColumn: { id: "1", elements: [] }, curDragElement: null, curDropElementId: null, dragStartPageY: null, isDragDown: false, }; }, computed: { ...mapState("free", ["curPage", "curElement"]), }, watch: { curPage: { immediate: true, handler(val) { this.selectColumn(val.columns && val.columns[0]); }, }, curElement(val) { if (!val.id) return; const columnIndex = this.curPage.columns.findIndex((column) => column.elements.find((elem) => elem.id === val.id) ); if (columnIndex === -1) return; this.selectColumn(this.curPage.columns[columnIndex]); this.$nextTick(() => { const tierDom = document.getElementById(`tier-${this.curElement.id}`); this.$refs.TierList.scrollTop = tierDom.offsetTop; }); }, }, methods: { ...mapMutations("free", ["setCurElement"]), ...mapActions("free", ["moveElementToElement"]), selectColumn(column) { if (column) { if (column.id === this.curColumn.id) return; this.curColumn = column; } else { this.curColumn = { id: "1", elements: [] }; } }, selectElement(element) { this.setCurElement(element); }, getRelateElement(dom) { let element = null; let parentNode = dom; while (!element && !parentNode.className.includes("tier-list")) { if ( !element && parentNode["id"] && parentNode["id"].includes("tier-element") ) { element = parentNode; } else { parentNode = parentNode.parentNode; } } return element; }, getElementId(tierId) { return tierId.replace("tier-", ""); }, checkElementsIsSiblings(elementId1, elementId2) { const pos1 = this.curColumn.elements.findIndex( (elem) => elem.id === elementId1 ); const pos2 = this.curColumn.elements.findIndex( (elem) => elem.id === elementId2 ); return Math.abs(pos1 - pos2) <= 1; }, getSiblingElement(elementId, offset) { const pos = this.curColumn.elements.findIndex( (elem) => elem.id === elementId ); return this.curColumn.elements[pos + offset] || null; }, dragStart(e, element) { this.dragStartPageY = e.pageY; this.curDragElement = element; }, dragOver(e) { // console.log(e.target); this.isDragDown = e.pageY > this.dragStartPageY; if (e.target.className.includes("tier-list")) { const curDropElement = this.isDragDown ? this.curColumn.elements.slice(-1)[0] : this.curColumn.elements[0]; this.curDropElementId = curDropElement.id; return; } const elementDom = this.getRelateElement(e.target); if (!elementDom) return; const targetId = this.getElementId(elementDom.id); const curDropElement = this.getSiblingElement(targetId, 0); this.curDropElementId = curDropElement.id; }, dropInnerElement() { // console.log(this.curDragElement.id, this.curDropElementId); if (this.curDragElement.id === this.curDropElementId) return; // 往下:target上一个位置 // 往上:target下一个位置 this.moveElementToElement({ curElement: this.curDragElement, toElementId: this.curDropElementId, curColumnId: this.curColumn.id, isDragDown: this.isDragDown, }); }, dragEnd() { this.curDragElement = null; this.curDropElementId = null; this.dragStartPageY = null; }, }, }; </script>