Procházet zdrojové kódy

✨ feat(split): implement draggable file list with improved UI

Shinohara Haruna před 6 měsíci
rodič
revize
a2075cc532
1 změnil soubory, kde provedl 71 přidání a 72 odebrání
  1. 71 72
      smsb-plus-ui/src/views/smsb/item/split.vue

+ 71 - 72
smsb-plus-ui/src/views/smsb/item/split.vue

@@ -39,84 +39,72 @@
       <!-- 右侧内容 -->
       <div class="w-1/3 p-2">
         <div v-if="screenNum === '1'" class="table-container">
-          <el-table ref="selectedTable" :data="selectedFiles1" border>
-            <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80">
-              <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 v-model="row.duration" :min="1" :max="300"></el-input-number>
-              </template>
-            </el-table-column>
-          </el-table>
+          <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="selectedFiles1" item-key="id" @end="onSelectedFilesDragEnd('1')" :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">{{ index + 1 }}</span>
+                <span style="flex: 1; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;">{{ element.name }}</span>
+                <el-input-number v-model="element.duration" :min="1" :max="300" style="width: 120px; margin-left: 8px" />
+              </div>
+            </template>
+          </draggable>
+          <div v-if="selectedFiles1.length === 0" style="text-align: center; color: #999; padding: 16px 0">暂无数据</div>
         </div>
         <div v-if="screenNum === '2'" class="table-container">
-          <el-table ref="selectedTable" :data="selectedFiles2" border>
-            <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80">
-              <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 v-model="row.duration" :min="1" :max="300"></el-input-number>
-              </template>
-            </el-table-column>
-          </el-table>
+          <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="selectedFiles2" item-key="id" @end="onSelectedFilesDragEnd('2')" :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">{{ index + 1 }}</span>
+                <span style="flex: 1; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;">{{ element.name }}</span>
+                <el-input-number v-model="element.duration" :min="1" :max="300" style="width: 120px; margin-left: 8px" />
+              </div>
+            </template>
+          </draggable>
+          <div v-if="selectedFiles2.length === 0" style="text-align: center; color: #999; padding: 16px 0">暂无数据</div>
         </div>
         <div v-if="screenNum === '3'" class="table-container">
-          <el-table ref="selectedTable" :data="selectedFiles3" border>
-            <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80">
-              <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 v-model="row.duration" :min="1" :max="300"></el-input-number>
-              </template>
-            </el-table-column>
-          </el-table>
+          <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="selectedFiles3" item-key="id" @end="onSelectedFilesDragEnd('3')" :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">{{ index + 1 }}</span>
+                <span style="flex: 1; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;">{{ element.name }}</span>
+                <el-input-number v-model="element.duration" :min="1" :max="300" style="width: 120px; margin-left: 8px" />
+              </div>
+            </template>
+          </draggable>
+          <div v-if="selectedFiles3.length === 0" style="text-align: center; color: #999; padding: 16px 0">暂无数据</div>
         </div>
         <div v-if="screenNum === '4'" class="table-container">
-          <el-table ref="selectedTable" :data="selectedFiles4" border>
-            <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80">
-              <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 v-model="row.duration" :min="1" :max="300"></el-input-number>
-              </template>
-            </el-table-column>
-          </el-table>
+          <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="selectedFiles4" item-key="id" @end="onSelectedFilesDragEnd('4')" :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">{{ index + 1 }}</span>
+                <span style="flex: 1; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;">{{ element.name }}</span>
+                <el-input-number v-model="element.duration" :min="1" :max="300" style="width: 120px; margin-left: 8px" />
+              </div>
+            </template>
+          </draggable>
+          <div v-if="selectedFiles4.length === 0" style="text-align: center; color: #999; padding: 16px 0">暂无数据</div>
         </div>
       </div>
     </div>
@@ -132,6 +120,7 @@
 </template>
 
 <script setup name="ItemSplit" lang="ts">
+import draggable from 'vuedraggable';
 import { MinioDataQuery, MinioDataVO } from '@/api/smsb/source/minioData_type';
 import { splitItemInfo, updateItem, updateItemSplit } from '@/api/smsb/source/item';
 import { listMinioData } from '@/api/smsb/source/minioData';
@@ -292,6 +281,16 @@ const cancel = () => {
   proxy.$router.push('/source/item');
 };
 
+const onSelectedFilesDragEnd = (screen: string) => () => {
+  let selectedFilesRef;
+  if (screen === '1') selectedFilesRef = selectedFiles1;
+  if (screen === '2') selectedFilesRef = selectedFiles2;
+  if (screen === '3') selectedFilesRef = selectedFiles3;
+  if (screen === '4') selectedFilesRef = selectedFiles4;
+  if (!selectedFilesRef) return;
+  selectedFilesRef.value = selectedFilesRef.value.map((f, idx) => ({ ...f, order: idx + 1 }));
+};
+
 onMounted(() => {
   getParamItemId();
   getFileList();