Selaa lähdekoodia

拖动逻辑修改

zhangjie 2 vuotta sitten
vanhempi
commit
d547c48619

+ 4 - 4
card/modules/free/components/ElementTierEdit.vue

@@ -59,7 +59,7 @@ export default {
       curColumn: { id: "1", elements: [] },
       curDragElement: null,
       curDropElementId: null,
-      dragStartScreenY: null,
+      dragStartPageY: null,
       isDragDown: false
     };
   },
@@ -132,12 +132,12 @@ export default {
       return this.curColumn.elements[pos + offset] || null;
     },
     dragStart(e, element) {
-      this.dragStartScreenY = e.screenY;
+      this.dragStartPageY = e.pageY;
       this.curDragElement = element;
     },
     dragOver(e) {
       // console.log(e.target);
-      this.isDragDown = e.screenY > this.dragStartScreenY;
+      this.isDragDown = e.pageY > this.dragStartPageY;
       if (e.target.className.includes("tier-list")) {
         const curDropElement = this.isDragDown
           ? this.curColumn.elements.slice(-1)[0]
@@ -169,7 +169,7 @@ export default {
     dragEnd() {
       this.curDragElement = null;
       this.curDropElementId = null;
-      this.dragStartScreenY = null;
+      this.dragStartPageY = null;
     }
   }
 };

+ 26 - 0
src/assets/styles/pages.scss

@@ -1197,7 +1197,33 @@
     height: 246px;
   }
   .field-item {
+    position: relative;
     padding: 5px 0;
     line-height: 20px;
+
+    &.after-drop {
+      &::after {
+        content: "";
+        display: block;
+        position: absolute;
+        width: 100%;
+        border-bottom: 2px solid $--color-primary;
+        bottom: -2px;
+        left: 0;
+        z-index: 9;
+      }
+    }
+    &.before-drop {
+      &::before {
+        content: "";
+        display: block;
+        position: absolute;
+        width: 100%;
+        border-top: 2px solid $--color-primary;
+        top: -2px;
+        left: 0;
+        z-index: 9;
+      }
+    }
   }
 }

+ 103 - 3
src/modules/base/components/RuleFieldEdit.vue

@@ -34,8 +34,27 @@
           >目的字段</el-checkbox
         >
       </div>
-      <div class="field-body">
-        <div v-for="item in targetList" :key="item.code" class="field-item">
+      <div
+        class="field-body"
+        @drop.prevent="dropInnerElement"
+        @dragover.prevent="dragOver($event)"
+        @dragleave.prevent
+      >
+        <div
+          v-for="item in targetList"
+          :key="item.code"
+          :class="[
+            'field-item',
+            {
+              'after-drop': item.code === curDropElementCode && isDragDown,
+              'before-drop': item.code === curDropElementCode && !isDragDown
+            }
+          ]"
+          :id="`field-item-${item.code}`"
+          draggable="true"
+          @dragstart="$event => dragStart($event, item)"
+          @dragend.prevent="dragEnd"
+        >
           <el-checkbox v-model="item.checked" @change="targetItemChange">{{
             item.name
           }}</el-checkbox>
@@ -69,7 +88,12 @@ export default {
       sourceAll: false,
       sourceList: [],
       targetAll: false,
-      targetList: []
+      targetList: [],
+      // drag
+      curDragElement: null,
+      curDropElementCode: null,
+      dragStartPageY: null,
+      isDragDown: false
     };
   },
   watch: {
@@ -157,6 +181,82 @@ export default {
       });
       this.$emit("input", targetFields);
       this.$emit("change", targetFields);
+    },
+    // drag
+    getRelateElement(dom) {
+      let element = null;
+      let parentNode = dom;
+      while (!element && !parentNode.className.includes("field-body")) {
+        if (
+          !element &&
+          parentNode["id"] &&
+          parentNode["id"].includes("field-item")
+        ) {
+          element = parentNode;
+        } else {
+          parentNode = parentNode.parentNode;
+        }
+      }
+
+      return element;
+    },
+    getElementCode(fieldId) {
+      return fieldId.replace("field-item-", "");
+    },
+    getSiblingElement(fieldCode, offset) {
+      const pos = this.targetList.findIndex(elem => elem.code === fieldCode);
+      return this.targetList[pos + offset] || null;
+    },
+    moveElementToElement(curElement, toElementCode, isDragDown) {
+      const curPos = this.targetList.findIndex(
+        elem => elem.code === curElement.code
+      );
+      this.targetList.splice(curPos, 1);
+
+      const toPos = this.targetList.findIndex(
+        elem => elem.code === toElementCode
+      );
+      const offset = isDragDown ? 1 : 0;
+      this.targetList.splice(toPos + offset, 0, { ...curElement });
+      this.emitChange();
+    },
+    dragStart(e, element) {
+      this.dragStartPageY = e.pageY;
+      this.curDragElement = element;
+    },
+    dragOver(e) {
+      // console.log(e);
+      this.isDragDown = e.pageY > this.dragStartPageY;
+      if (e.target.className.includes("field-body")) {
+        const curDropElement = this.isDragDown
+          ? this.targetList.slice(-1)[0]
+          : this.targetList[0];
+        this.curDropElementCode = curDropElement.code;
+        return;
+      }
+
+      const elementDom = this.getRelateElement(e.target);
+      if (!elementDom) return;
+
+      const fieldCode = this.getElementCode(elementDom.id);
+      const curDropElement = this.getSiblingElement(fieldCode, 0);
+      this.curDropElementCode = curDropElement.code;
+    },
+    dropInnerElement() {
+      if (this.curDragElement.code === this.curDropElementCode) return;
+
+      // 往下:target上一个位置
+      // 往上:target下一个位置
+      this.moveElementToElement(
+        this.curDragElement,
+        this.curDropElementCode,
+        this.isDragDown
+      );
+    },
+    dragEnd() {
+      this.curDragElement = null;
+      this.curDropElementCode = null;
+      this.dragStartPageY = null;
     }
   }
 };