Procházet zdrojové kódy

✨feat(item): implement draggable file list with vuedraggable

Shinohara Haruna před 6 měsíci
rodič
revize
7fdec8363f

+ 1 - 0
smsb-plus-ui/package.json

@@ -47,6 +47,7 @@
     "vue-i18n": "9.10.2",
     "vue-router": "4.3.2",
     "vue-types": "5.1.1",
+    "vuedraggable": "^4.1.0",
     "vxe-table": "4.5.22"
   },
   "devDependencies": {

+ 31 - 20
smsb-plus-ui/src/views/smsb/item/index.vue

@@ -137,26 +137,31 @@
 
         <!-- 右侧选中文件列表 -->
         <div class="selected-container">
-          <el-table ref="selectedTable" :data="selectedFiles" border>
-            <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80" prop="order">
-              <template #default="{ row }">
-                <span class="order-number">{{ row.order }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="文件名">
-              <template #default="{ row }">
-                <span>{{ row.name }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="播放时长">
-              <template #default="{ row }">
-                <el-input-number :disabled="row.type !== 1" v-model="row.duration" :min="1"
-                  :max="300"></el-input-number>
-              </template>
-            </el-table-column>
-          </el-table>
-        </div>
+  <!-- 自定义表头 -->
+  <div class="draggable-header" style="display: flex; align-items: center; background: #fafafa; border-bottom: 1px solid #eee; min-height: 48px; font-weight: bold;">
+    <span style="width:80px; text-align:center;">排序</span>
+    <span style="flex:1;">文件名</span>
+    <span style="width:120px; margin-left:8px;">播放时长</span>
+  </div>
+  <!-- 拖拽列表体 -->
+  <draggable
+    v-model="selectedFiles"
+    item-key="id"
+    @end="onSelectedFilesDragEnd"
+    :animation="200"
+    tag="div"
+  >
+    <template #item="{ element, index }">
+      <div class="draggable-row" :draggable="true" style="display: flex; align-items: center; border-bottom: 1px solid #eee; min-height: 48px; cursor: move;">
+        <span class="order-number" style="width:80px; text-align:center;">{{ element.order }}</span>
+        <span style="flex:1;">{{ element.name }}</span>
+        <el-input-number :disabled="element.type !== 1" v-model="element.duration" :min="1" :max="300" style="width:120px; margin-left:8px;" />
+      </div>
+    </template>
+  </draggable>
+  <!-- 空数据提示 -->
+  <div v-if="selectedFiles.length === 0" style="text-align:center; color:#999; padding: 16px 0;">暂无数据</div>
+</div>
       </div>
       <template #footer>
         <div class="dialog-footer">
@@ -279,6 +284,7 @@
 </template>
 
 <script setup name="Item" lang="ts">
+import draggable from 'vuedraggable';
 import { listItem, getItem, delItem, addItem, updateItem, itemStatistics } from '@/api/smsb/source/item';
 import { ItemVO, ItemQuery, ItemForm } from '@/api/smsb/source/item_type';
 import { MinioDataQuery, MinioDataVO } from '@/api/smsb/source/minioData_type';
@@ -617,6 +623,11 @@ const getItemStatistics = async () => {
   }
 };
 
+/** 拖拽排序结束时,重排 order 字段 */
+const onSelectedFilesDragEnd = () => {
+  selectedFiles.value = selectedFiles.value.map((f, idx) => ({ ...f, order: idx + 1 }));
+};
+
 onMounted(() => {
   getList();
   getItemStatistics();