Просмотр исходного кода

✨feat(item): improve file selection persistence and ordering logic

Shinohara Haruna 6 месяцев назад
Родитель
Сommit
04a5e630e4
1 измененных файлов с 60 добавлено и 45 удалено
  1. 60 45
      smsb-plus-ui/src/views/smsb/item/index.vue

+ 60 - 45
smsb-plus-ui/src/views/smsb/item/index.vue

@@ -114,7 +114,7 @@
           <!-- 界面名称输入框 -->
           <el-input v-model="itemName" placeholder="请输入轮播组名称" class="interface-input"></el-input>
 
-          <el-table :data="minioDataList" reserve-selection row-key="id" @selection-change="handleSelectionFile">
+          <el-table ref="fileTable" :data="minioDataList" reserve-selection row-key="id" @selection-change="handleSelectionFile">
             <el-table-column type="selection" width="55" header-align="center" />
             <el-table-column label="类型" header-align="center" prop="type" width="80">
               <template #default="scope">
@@ -139,7 +139,7 @@
         <div class="selected-container">
           <el-table ref="selectedTable" :data="selectedFiles" border>
             <!-- 显示排序数字 -->
-            <el-table-column label="排序" width="80">
+            <el-table-column label="排序" width="80" prop="order">
               <template #default="{ row }">
                 <span class="order-number">{{ row.order }}</span>
               </template>
@@ -283,8 +283,8 @@ import { listItem, getItem, delItem, addItem, updateItem, itemStatistics } from
 import { ItemVO, ItemQuery, ItemForm } from '@/api/smsb/source/item_type';
 import { MinioDataQuery, MinioDataVO } from '@/api/smsb/source/minioData_type';
 import { listMinioData } from '@/api/smsb/source/minioData';
-import Sortable from 'sortablejs';
 import { nextTick } from 'vue';
+import type { ElTable } from 'element-plus';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { smsb_item_type, smsb_split_screen, smsb_source_type, smsb_yes_no } = toRefs<any>(
@@ -310,6 +310,7 @@ const positionH = ref(0);
 const itemName = ref<string>('');
 const queryFormRef = ref<ElFormInstance>();
 const itemFormRef = ref<ElFormInstance>();
+const fileTable = ref<InstanceType<typeof ElTable>>();
 const minioDataList = ref<MinioDataVO[]>([]);
 const dateRangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
 
@@ -384,18 +385,69 @@ const getList = async () => {
 };
 /** 查询文件资源列表 */
 const getFileList = async () => {
+  loading.value = true;
   try {
     const res = await listMinioData(dialogQueryParams.value);
     minioDataList.value = res.rows.map((data) => ({
-  ...data,
-  size: (parseFloat(data.size) / 1024).toFixed(3) + 'MB'
-}));
+      ...data,
+      size: (parseFloat(data.size) / 1024).toFixed(3) + 'MB'
+    }));
     fileTotal.value = res.total;
-  } catch (e: any) {
-    proxy?.$modal.msgError(e?.message || '获取文件资源失败');
+    // After data loads, restore selections
+    nextTick(() => {
+      if (selectedFiles.value?.length) {
+        const selectedIds = new Set(selectedFiles.value.map(f => f.id));
+        minioDataList.value.forEach(row => {
+          if (selectedIds.has(row.id)) {
+            fileTable.value?.toggleRowSelection(row, true);
+          }
+        });
+      }
+    });
+  } finally {
+    loading.value = false;
   }
 };
 
+/** 多选框选中文件数据 */
+const handleSelectionFile = (selection: MinioDataVO[]) => {
+  // Get IDs of newly selected items
+  const newSelectionIds = new Set(selection.map(item => item.id));
+  
+  // Preserve existing selections that weren't in this batch
+  const preservedSelections = selectedFiles.value.filter(
+    f => !newSelectionIds.has(f.id)
+  );
+
+  // Get existing selections that were in this batch (to preserve their order)
+  const existingSelections = selectedFiles.value.filter(
+    f => newSelectionIds.has(f.id)
+  );
+
+  // Get max order number from preserved selections
+  const maxOrder = preservedSelections.length > 0 
+    ? Math.max(...preservedSelections.map(f => f.order))
+    : 0;
+
+  // Create new selections with proper ordering
+  const newSelections = selection
+    .filter(item => !existingSelections.some(f => f.id === item.id))
+    .map((item, index) => ({
+      id: item.id,
+      name: item.originalName,
+      type: item.type,
+      duration: item.type === 1 ? 10 : item.duration,
+      order: maxOrder + index + 1
+    }));
+
+  // Combine and sort all selections by order number
+  selectedFiles.value = [
+    ...preservedSelections,
+    ...existingSelections,
+    ...newSelections
+  ].sort((a, b) => a.order - b.order);
+};
+
 /** 取消按钮 */
 const cancel = () => {
   reset();
@@ -429,29 +481,6 @@ const handleSelectionChange = (selection: ItemVO[]) => {
   multiple.value = !selection.length;
 };
 
-/** 多选框选中文件数据 */
-const handleSelectionFile = (selection: MinioDataVO[]) => {
-  selectedFiles.value = selection.map((item: any, index: number) => ({
-    id: item.id,
-    name: item.originalName,
-    type: item.type,
-    duration: item.type === 1 ? 10 : item.duration, // 默认播放时长 10s
-    order: index + 1 // 默认排序号
-  }));
-};
-
-// 重新编号排序
-const updateOrder = () => {
-  selectedFiles.value.forEach((item, index) => {
-    item.order = index + 1;
-  });
-};
-
-// 删除选中文件
-const removeFile = (file: any) => {
-  selectedFiles.value = selectedFiles.value.filter((f) => f.id !== file.id);
-};
-
 /** 新增轮播按钮操作 */
 const handleAddL = () => {
   reset();
@@ -597,19 +626,6 @@ const getItemStatistics = async () => {
 onMounted(() => {
   getList();
   getItemStatistics();
-  nextTick(() => {
-    const tableEl = document.querySelector('.selected-container .el-table__body-wrapper tbody') as HTMLElement;
-    Sortable.create(tableEl, {
-      animation: 150,
-      handle: '.order-number', // 允许拖拽
-      onEnd(event) {
-        const { oldIndex, newIndex } = event;
-        const movedItem = selectedFiles.value.splice(oldIndex!, 1)[0];
-        selectedFiles.value.splice(newIndex!, 0, movedItem);
-        updateOrder(); // 拖拽后重新排序
-      }
-    });
-  });
 });
 </script>
 <style scoped>
@@ -631,7 +647,6 @@ onMounted(() => {
 }
 
 .order-number {
-  cursor: grab;
   display: inline-block;
   width: 30px;
   text-align: center;