Explorar o código

查看附件拖拽修改

duy hai 1 mes
pai
achega
56465e19d1
Modificáronse 1 ficheiros con 117 adicións e 73 borrados
  1. 117 73
      src/views/data-fill/wbs.vue

+ 117 - 73
src/views/data-fill/wbs.vue

@@ -1236,9 +1236,9 @@
         />
 
         <!-- 查看附件 -->
+    
         <hc-new-dialog
             v-model="attachmentModal"
-         
             is-table
             title="附件列表"
             widths="780px"
@@ -1251,13 +1251,12 @@
                     <span class="text-orange">按住鼠标拖动文件可进行附件列表排序</span>
                 </div>
                 <div
-                    v-for="item in attachmentList"
+                    v-for="(item, index) in attachmentList"
                     :key="item.id"
                     class="hc-attachment-card"
                 >
                     <div class="hc-attachment-header">
                         {{ item?.nodeName }}
-                        <!-- <el-button type="success" :loading="saveFileOrderLoad" style="float:right" @click="saveFileOrder">确定排序</el-button> -->
                     </div>
                     <div 
                         :ref="setAttachmentListRef"
@@ -1267,9 +1266,10 @@
                             v-for="item1 in item.fileList"
                             :key="item1.id"
                             class="hc-attachment-item"
+                            :data-id="item1.id"
                         >
                             <div class="hc-attachment-file-name">
-                                <HcIcon name="drag-move-2" class="text-blue" />
+                                <HcIcon name="drag-move-2" class="drag-handle text-blue" />
                                 <HcIcon name="attachment" class="ml-2" />
                                 <div class="name">{{ item1?.name }}</div>
                             </div>
@@ -1302,9 +1302,17 @@
             </div>
             <template #footer>
                 <el-button @click="attachmentModal = false">关闭</el-button>
-                <el-button type="primary" :loading="saveFileOrderLoad" :disabled="attachmentList.length === 0" @click="saveFileOrder">确定排序</el-button>
+                <el-button 
+                    type="primary" 
+                    :loading="saveFileOrderLoad" 
+                    :disabled="attachmentList.length === 0" 
+                    @click="saveFileOrder"
+                >
+                    确定排序
+                </el-button>
             </template>
         </hc-new-dialog>
+    
         <!-- 上传文件 -->
         <hc-new-dialog
             v-model="uploadModal"
@@ -1419,7 +1427,7 @@
 </template>
 
 <script setup>
-import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
+import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { useAppStore } from '~src/store'
 import { HcIsButton } from '~src/plugins/IsButtons'
@@ -1543,8 +1551,16 @@ onMounted(() => {
     getDictionaryApi()
     getStandardTypeOptions()
     getMajorDataTypeOptions()
+    nextTick(() => {
+    initDragAndDrop()
+  })
+})
+// 组件卸载前清理事件
+onBeforeUnmount(() => {
+  attachmentListRefs.value.forEach(container => {
+    container.removeEventListener('dragover', () => {})
+  })
 })
-
 //身份按钮切换数据
 const authBtnTabKey = ref('1')
 
@@ -3095,9 +3111,9 @@ const attachmentModalShow = () => {
     attachmentModal.value = true
 
     getAttachmentList()
-    nextTick(()=>{
-          initSortable()
-    })
+    // nextTick(()=>{
+    //       initSortable()
+    // })
 }
 const attachmentListLoaing = ref(false)
 const attachmentList = ref([])
@@ -3123,37 +3139,71 @@ const getAttachmentList = async () => {
 const attachmentListRefs = ref([])
 const sortableInstances = ref([]) 
 
+
+
+
+// 设置附件列表的ref
 const setAttachmentListRef = (el) => {
   if (el) {
     attachmentListRefs.value.push(el)
   }
 }
 
-// 初始化拖拽排序
-const initSortable = () => {
-  nextTick(() => {
-    attachmentListRefs.value.forEach((el, index) => {
-      const sortable = new Sortable(el, {
-        animation: 150,
-        ghostClass: 'sortable-ghost',
-        handle: '.hc-attachment-item', // 整个条目可拖拽
-        onEnd: (evt) => {
-          const { oldIndex, newIndex } = evt
-          if (oldIndex !== newIndex) {
-            // 更新对应节点的文件顺序
-            const node = attachmentList.value[index]
-            const [movedItem] = node.fileList.splice(oldIndex, 1)
-            node.fileList.splice(newIndex, 0, movedItem)
-            
-            // // 这里可以调用API保存新的顺序
-  
-          }
-        },
+// 初始化拖拽功能
+const initDragAndDrop = () => {
+  attachmentListRefs.value.forEach((container) => {
+    const items = container.querySelectorAll('.hc-attachment-item')
+    
+    items.forEach((item) => {
+      item.draggable = true
+      
+      // 拖拽开始事件
+      item.addEventListener('dragstart', (e) => {
+        e.dataTransfer.setData('text/plain', item.dataset.id)
+        item.classList.add('dragging')
+        setTimeout(() => {
+          item.style.display = 'none'
+        }, 0)
+      })
+      
+      // 拖拽结束事件
+      item.addEventListener('dragend', () => {
+        items.forEach(i => {
+          i.classList.remove('dragging')
+          i.style.display = ''
+        })
       })
-      sortableInstances.value.push(sortable) // 存储 Sortable 实例引用
+    })
+    
+    // 拖拽经过事件
+    container.addEventListener('dragover', (e) => {
+      e.preventDefault()
+      const draggingItem = container.querySelector('.dragging')
+      const afterElement = getDragAfterElement(container, e.clientY)
+      
+      if (afterElement) {
+        container.insertBefore(draggingItem, afterElement)
+      } else {
+        container.appendChild(draggingItem)
+      }
     })
   })
 }
+// 获取拖拽后应该放置的位置
+const getDragAfterElement = (container, y) => {
+  const draggableElements = [...container.querySelectorAll('.hc-attachment-item:not(.dragging)')]
+  
+  return draggableElements.reduce((closest, child) => {
+    const box = child.getBoundingClientRect()
+    const offset = y - box.top - box.height / 2
+    
+    if (offset < 0 && offset > closest.offset) {
+      return { element: child, offset: offset }
+    } else {
+      return closest
+    }
+  }, { offset: Number.NEGATIVE_INFINITY }).element
+}
 // 销毁 Sortable 实例
 const destroySortableInstances = () => {
   sortableInstances.value.forEach(instance => {
@@ -3167,7 +3217,7 @@ watch(attachmentModal, (newVal) => {
   if (!newVal) {
     destroySortableInstances() // 关闭弹窗时销毁 Sortable 实例
   } else {
-    initSortable() // 打开弹窗时初始化 Sortable
+    initDragAndDrop() // 打开弹窗时初始化 Sortable
   }
 })
 onUnmounted(() => {
@@ -3184,14 +3234,14 @@ const saveFileOrder = async () => {
     if (!error && code === 200) {
        window?.$message?.success(msg)
        getAttachmentList()
-         initSortable()
+         initDragAndDrop()
     } 
 }
 
 // 监听attachmentList变化时初始化拖拽
 watch(() => attachmentList.value, () => {
      nextTick(()=>{
-          initSortable()
+          initDragAndDrop()
     })
 }, { deep: true })
 //预览
@@ -3851,57 +3901,51 @@ html.theme-dark {
 }
 </style>
 
-<style lang="scss" scoped>
-/* 新增拖拽排序相关样式 */
-.sortable-ghost {
-  opacity: 0.5;
-  background: #f5f5f5;
+<style scoped>
+.hc-attachment-content {
+  min-height: 20px;
+  padding: 10px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
 }
 
 .hc-attachment-item {
-  transition: all 0.3s;
-  cursor: move;
   display: flex;
   justify-content: space-between;
   align-items: center;
-  padding: 12px;
+  padding: 10px;
   margin-bottom: 8px;
-  background: #fff;
-  border-radius: 4px;
+  background-color: white;
   border: 1px solid #ebeef5;
-  
-  &:hover {
-    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  }
+  border-radius: 4px;
+  cursor: move;
+  transition: all 0.3s;
 }
 
-.hc-attachment-content {
-  min-height: 20px;
+.hc-attachment-item:hover {
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
 }
 
-/* 原有样式保持不变 */
-.hc-attachment-card {
-  margin-bottom: 16px;
-  
-  .hc-attachment-header {
-    font-weight: bold;
-    margin-bottom: 8px;
-    padding-left: 8px;
-    border-left: 3px solid #409eff;
+.hc-attachment-item.dragging {
+  opacity: 0.5;
+  background-color: #f5f7fa;
+}
 
-  }
-  
-  .hc-attachment-file-name {
-    display: flex;
-    align-items: center;
-    
-    .name {
-      margin-left: 8px;
-    }
-  }
-  
-  .hc-attachment-btn-box {
-    display: flex;
-  }
+.hc-attachment-file-name {
+  display: flex;
+  align-items: center;
+  flex: 1;
+}
+
+.hc-attachment-file-name .name {
+  margin-left: 8px;
+  max-width: 300px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.drag-handle {
+  cursor: move;
 }
 </style>