Explorar el Código

feat: 附件新增拖动排序

johnsen hace 2 semanas
padre
commit
6ae756eaef

+ 29 - 24
src/business/platform/file/attachment/index.vue

@@ -64,20 +64,15 @@
       ]"
     >
       <vue-draggable
-        v-model="sortList"
+        :list="localItems"
         v-bind="draggableOptions"
         class="list-group"
-        @start="isDragging = true"
-        @end="
-          () => {
-            isDragging = false
-          }
-        "
-        @update="updateSort"
+        @end="handleDragEnd"
       >
         <li
-          v-for="(file, index) in displayedList"
+          v-for="(file, index) in localItems"
           :key="index"
+          v-show="isExpanded || index < 5"
           :class="['el-upload-list__item', focusing ? 'focusing' : '']"
           tabindex="0"
           @focus="focusing = true"
@@ -91,6 +86,7 @@
               :title="file"
               @click.stop="handlePreview(index)"
             >
+              <i class="el-icon-rank draggable" v-if="editable" />
               <i class="el-icon-document" />{{ file | ellipsis }}
             </a>
             <label class="tools">
@@ -112,10 +108,6 @@
               <el-divider direction="vertical" />
               <template v-if="editable">
                 <!--默认附件上传 -->
-                <!-- <el-tooltip effect="dark" content="拖拽排序" placement="bottom-start">
-                                    <el-link type="info" :underline="false" icon="ibps-icon-arrows" class="draggable">&nbsp;</el-link>
-                                </el-tooltip>
-                                <el-divider direction="vertical" /> -->
                 <el-tooltip
                   effect="dark"
                   content="重新选择"
@@ -258,8 +250,6 @@ export default {
       listType: 'text',
       focusing: false,
       defaultDisabled: true,
-      sortList: [],
-      isDragging: false,
       draggableOptions: {
         handle: '.draggable',
         ghostClass: 'sortable-ghost',
@@ -268,15 +258,16 @@ export default {
         animation: 200,
         axis: 'y'
       },
-      isExpanded: false
+      isExpanded: false,
+      localItems: [] // 本地拷贝用于拖拽
     }
   },
   computed: {
     // 是否允许上传
     uploadable() {
       if (this.readonly) return false
-      if (!this.multiple && this.items.length >= 1) return false
-      if (this.multiple && this.limit && this.items.length >= this.limit)
+      if (!this.multiple && this.localItems.length >= 1) return false
+      if (this.multiple && this.limit && this.localItems.length >= this.limit)
         return false
       return true
     },
@@ -288,10 +279,19 @@ export default {
       return 30 * length + 'px'
     },
     shouldShowButton() {
-      return this.items.length > 5
+      return this.localItems.length > 5
     },
     displayedList() {
-      return this.isExpanded ? this.items : this.items.slice(0, 5)
+      return this.isExpanded ? this.localItems : this.localItems.slice(0, 5)
+    }
+  },
+  watch: {
+    items: {
+      handler(val) {
+        this.localItems = [...(val || [])]
+      },
+      immediate: true,
+      deep: true
     }
   },
   methods: {
@@ -338,6 +338,10 @@ export default {
     handlePreview(index) {
       this.$emit('action-event', 'preview', index)
     },
+    // 处理拖拽排序事件
+    handleSortEvent({ oldIndex, newIndex, sortedItems }) {
+      this.$emit('sort-change', sortedItems)
+    },
     // 默认上传模块
     httpRequest(options) {
       return uploadFile(options.file, {})
@@ -461,10 +465,11 @@ export default {
       }
       this.$emit('action-event', 'confirm', data)
     },
-    updateSort({ to, from, item, clone, oldIndex, newlndex }) {
-      // console.log(to, from, item, clone, oldIndex, newlndex)
-      // console.log(this.value)
-      // console.log(this.sortList)
+    handleDragEnd(evt) {
+      const { oldIndex, newIndex } = evt
+      if (oldIndex === newIndex) return
+      // 通知 selector.vue 处理排序
+      this.$emit('action-event', 'sort', newIndex, { oldIndex, newIndex })
     }
   }
 }

+ 23 - 1
src/business/platform/file/attachment/selector.vue

@@ -488,8 +488,26 @@ export default {
         case 'edit': // 编辑
           this.handleEdit(index, data, type)
           break
+        case 'sort': // 拖拽排序
+          console.log('拖拽排序', index, data)
+          this.handleSortAction(data)
+          break
       }
     },
+    // 处理拖拽排序
+    handleSortAction(data) {
+      console.log('拖拽排序', data)
+      const { oldIndex, newIndex } = data || {}
+      if (oldIndex == null || newIndex == null) return
+      if (oldIndex === newIndex) return
+      // 从 selectorValue 中交换对应位置的数据
+      const item = this.selectorValue.splice(oldIndex, 1)[0]
+      this.selectorValue.splice(newIndex, 0, item)
+      // 同步更新缓存数据顺序
+      this.setCacheData()
+      // 触发值更新
+      this.handleInput()
+    },
     // 处理编辑文件
     handleEdit(index, data, type) {
       // 1、获取文件数据 及下载流接口
@@ -567,7 +585,11 @@ export default {
           newTab.document.write('<style>body { margin: 0px; }</style>')
           newTab.document.head.appendChild(link)
           newTab.document.write(
-            `<iframe src="${this.$baseUrl}lib/pdfjs-dist/web/viewer.html?file=${encodeURIComponent(url)}&hasRole=${hasRole}" style="width:100%; height:100%;" frameborder="0";>`
+            `<iframe src="${
+              this.$baseUrl
+            }lib/pdfjs-dist/web/viewer.html?file=${encodeURIComponent(
+              url
+            )}&hasRole=${hasRole}" style="width:100%; height:100%;" frameborder="0";>`
           )
           // this.closeDialog()
         })

+ 22 - 1
src/business/platform/file/attachment/template-selector.vue

@@ -501,8 +501,25 @@ export default {
         case 'edit': // 编辑
           this.handleEdit(data, 'edit', '_blank')
           break
+        case 'sort': // 拖拽排序
+          console.log('拖拽排序', index, data)
+          this.handleSortAction(data)
+          break
       }
     },
+    handleSortAction(data) {
+      console.log('拖拽排序', data)
+      const { oldIndex, newIndex } = data || {}
+      if (oldIndex == null || newIndex == null) return
+      if (oldIndex === newIndex) return
+      // 从 selectorValue 中交换对应位置的数据
+      const item = this.selectorValue.splice(oldIndex, 1)[0]
+      this.selectorValue.splice(newIndex, 0, item)
+      // 同步更新缓存数据顺序
+      this.setCacheData()
+      // 触发值更新
+      this.handleInput()
+    },
     // 处理编辑文件
     async handleEdit(data, mode, openType) {
       if (this.$utils.isEmpty(this.templateOption) && data.filepath) {
@@ -567,7 +584,11 @@ export default {
           newTab.document.write('<style>body { margin: 0px; }</style>')
           newTab.document.head.appendChild(link)
           newTab.document.write(
-            `<iframe src="${this.$baseUrl}lib/pdfjs-dist/web/viewer.html?file=${encodeURIComponent(url)}" style="width:100%; height:100%;" frameborder="0";>`
+            `<iframe src="${
+              this.$baseUrl
+            }lib/pdfjs-dist/web/viewer.html?file=${encodeURIComponent(
+              url
+            )}" style="width:100%; height:100%;" frameborder="0";>`
           )
           // this.closeDialog()
         })

+ 19 - 6
src/business/platform/file/attachment/template.vue

@@ -65,7 +65,7 @@
       ]"
     >
       <vue-draggable
-        v-model="sortList"
+        v-model="items"
         v-bind="draggableOptions"
         class="list-group"
         @start="isDragging = true"
@@ -92,6 +92,7 @@
               :title="file"
               @click.stop="handlePreview(index)"
             >
+              <i class="el-icon-rank draggable" v-if="editable" />
               <i class="el-icon-document" />{{ file | ellipsis }}
             </a>
             <label class="tools">
@@ -331,6 +332,7 @@ export default {
       } else {
         data = file.response.data
       }
+      console.log('handleSuccess', data)
       this.$emit('action-event', 'confirm', data)
     },
     getFileDataList(fileList) {
@@ -355,7 +357,11 @@ export default {
       if (this.fileSize && file.size > this.fileSize) {
         this.$message.closeAll()
         this.$message({
-          message: `上传文件的尺寸大于${this.$utils.formatSize(this.fileSize, 2, ['B', 'K', 'M', 'G', 'TB'])}`,
+          message: `上传文件的尺寸大于${this.$utils.formatSize(
+            this.fileSize,
+            2,
+            ['B', 'K', 'M', 'G', 'TB']
+          )}`,
           type: 'warning'
         })
         return false
@@ -435,10 +441,17 @@ export default {
       }
       this.$emit('action-event', 'confirm', data)
     },
-    updateSort({ to, from, item, clone, oldIndex, newlndex }) {
-      // console.log(to, from, item, clone, oldIndex, newlndex)
-      // console.log(this.value)
-      // console.log(this.sortList)
+    updateSort({ oldIndex, newIndex }) {
+      // 交换 items 数组中的位置
+      const item = this.items.splice(oldIndex, 1)[0]
+      this.items.splice(newIndex, 0, item)
+      // 同步更新 value(如果存在)
+      if (this.$utils.isNotEmpty(this.value) && Array.isArray(this.value)) {
+        const valItem = this.value.splice(oldIndex, 1)[0]
+        this.value.splice(newIndex, 0, valItem)
+      }
+      // 通知父组件排序已变更
+      this.$emit('action-event', 'sort', newIndex, { oldIndex, newIndex })
     }
   }
 }