yanghao 1 день назад
Родитель
Сommit
6de5acdc26
1 измененных файлов с 35 добавлено и 12 удалено
  1. 35 12
      src/views/expert/list/index.vue

+ 35 - 12
src/views/expert/list/index.vue

@@ -166,15 +166,21 @@
               </span>
 
               <template v-if="cell.type === 'members'">
-                <button
-                  v-for="member in cell.members"
-                  :key="member.id"
-                  type="button"
-                  class="member-link"
-                  @click="handleMemberClick(member)"
+                <draggable
+                  :list="cell.members"
+                  item-key="id"
+                  class="member-list"
+                  :animation="180"
+                  ghost-class="member-ghost"
+                  :group="{ name: `experts-${row.teamName}-${index}`, pull: false, put: false }"
+                  @end="handleExpertDragEnd(row, index, cell.members)"
                 >
-                  {{ member.expertName }}
-                </button>
+                  <template #item="{ element: member }">
+                    <button type="button" class="member-link" @click="handleMemberClick(member)">
+                      {{ member.expertName }}
+                    </button>
+                  </template>
+                </draggable>
               </template>
 
               <span v-else :class="['cell-text', cell.tone === 'danger' ? 'is-danger' : '']">
@@ -612,6 +618,7 @@ import * as DeptApi from '@/api/system/dept'
 import { defaultProps } from '@/utils/tree'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
 import { ElTable } from 'element-plus'
+import draggable from 'vuedraggable'
 
 const defaultFormData = () => ({
   id: undefined,
@@ -813,6 +820,7 @@ const selectedTeam = ref('')
 const wordCloudVisible = ref(false)
 const drawerVisible = ref(false)
 const activeExpert = ref<ExpertProfile | null>(null)
+const expertOrderMap = ref<Record<string, number[]>>({})
 
 const resetQueryParams = () => ({
   deptId: undefined,
@@ -997,12 +1005,21 @@ const tableData = computed<TableRow[]>(() => {
       )
       .join(' ')
       .toLowerCase()
-    const cells: CellItem[] = rankOptions.value.map((option) => ({
-      type: 'members',
-      members: group.experts.filter((expert) =>
+    const cells: CellItem[] = rankOptions.value.map((option) => {
+      const members = group.experts.filter((expert) =>
         (expert.expertRank || []).some((rank) => String(rank) === String(option.value))
       )
-    }))
+      const order = expertOrderMap.value[`${group.echelonLabel}-${option.value}`]
+      const orderIndex = new Map((order || []).map((id, order) => [id, order]))
+
+      members.sort(
+        (left, right) =>
+          (orderIndex.get(left.id) ?? Number.MAX_SAFE_INTEGER) -
+          (orderIndex.get(right.id) ?? Number.MAX_SAFE_INTEGER)
+      )
+
+      return { type: 'members', members }
+    })
 
     return {
       teamName: group.echelonLabel,
@@ -1018,6 +1035,12 @@ const tableData = computed<TableRow[]>(() => {
   })
 })
 
+const handleExpertDragEnd = (row: TableRow, cellIndex: number, members: ExpertItem[]) => {
+  expertOrderMap.value[`${row.teamName}-${rankOptions.value[cellIndex]?.value}`] = members.map(
+    (member) => member.id
+  )
+}
+
 const filteredTableData = computed(() => {
   return tableData.value.filter((row) => {
     const educationMatch = selectedEducation.value