<template>
  <el-dialog
    title="置顶排序"
    :visible.sync="dialogVisible"
    custom-class="g-dialog top-course-sorter-dialog"
    width="820px"
    :close-on-click-modal="false"
    @closed="handleClosed"
    append-to-body
  >
    <div class="top-course-sorter" v-loading="loading">
      <el-table
        v-if="topList.length"
        ref="sortTable"
        :data="topList"
        class="top-course-sorter__table"
        row-key="id"
        :row-class-name="getRowClassName"
        :header-cell-style="{ background: '#f5f7fa', color: '#303133', fontWeight: '600' }"
      >
        <el-table-column width="60" align="center">
          <template slot-scope="scope">
            <div class="drag-handle">
              <i class="el-icon-s-operation"></i>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序" width="80" align="left">
          <template slot-scope="scope">
            <span class="common-cell">{{ scope.$index + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="课程名称" min-width="200">
          <template slot-scope="scope">
            <el-tooltip :content="scope.row.name" placement="top" :disabled="!scope.row.name">
              <div class="cell-text common-cell">{{ scope.row.name }}</div>
            </el-tooltip>
          </template>
        </el-table-column>
        <el-table-column prop="teacherName" label="授课教师" :min-width="teacherColumnWidth" align="center">
          <template slot-scope="scope">
            <span class="common-cell">{{ scope.row.teacherName || '-' }}</span>
          </template>
        </el-table-column>
      </el-table>
      <el-empty v-else-if="!loading" description="暂无置顶课程"></el-empty>
    </div>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" :disabled="!topList.length" :loading="saving" @click="handleSave">确定</el-button>
    </span>
  </el-dialog>
</template>

<script>
import apiCourse from '@/api/modules/course.js';

export default {
  name: 'TopCourseSorter',
  computed: {
    // 动态计算"授课教师"列的最小宽度
    teacherColumnWidth() {
      return this.calcColumnWidth('授课教师', 'teacherName');
    },
  },
  data() {
    return {
      dialogVisible: false,
      loading: false,
      saving: false,
      topList: [],
      draggingIndex: null,
    };
  },
  watch: {
    topList: {
      handler(newVal, oldVal) {
        // 只在列表长度变化或首次加载时初始化拖拽事件
        if (!oldVal || newVal.length !== oldVal.length) {
          this.$nextTick(() => {
            this.initDragEvents();
          });
        }
      },
      immediate: false,
    },
  },
  methods: {
    open() {
      this.dialogVisible = true;
      this.fetchTopList();
    },
    async fetchTopList() {
      this.loading = true;
      try {
        const res = await apiCourse.fetchTopCourseList();
        if (res.status === 200) {
          this.topList = res.result.map(item=>{
            return {
              ...item,
              // teacherName: '对对对柳在一、李玉冰、李国鑫、张添瑞、张子峰、 柳在一、李玉冰、李国鑫、张添瑞、张子峰'
            }
          })
        } else {
          this.$message.error(res.message || '获取置顶课程失败');
          this.topList = [];
        }
      } catch (error) {
        this.$message.error(error.message || '获取置顶课程失败');
        this.topList = [];
      } finally {
        this.loading = false;
      }
    },
    getRowClassName({ row, rowIndex }) {
      if (this.draggingIndex === rowIndex) {
        return 'is-dragging';
      }
      return '';
    },
    initDragEvents() {
      if (!this.$refs.sortTable) return;
      
      const tableBody = this.$refs.sortTable.$el.querySelector('.el-table__body-wrapper tbody');
      if (!tableBody) return;

      const rows = tableBody.querySelectorAll('tr');
      rows.forEach((row, index) => {
        // 移除旧的事件监听器
        row.removeEventListener('dragstart', this.handleDragStart);
        row.removeEventListener('dragover', this.handleDragOver);
        row.removeEventListener('drop', this.handleDrop);
        row.removeEventListener('dragend', this.handleDragEnd);

        // 设置可拖拽
        row.draggable = true;
        row.setAttribute('data-index', index);

        // 添加新的事件监听器
        row.addEventListener('dragstart', (e) => this.handleDragStart(index, e));
        row.addEventListener('dragover', (e) => this.handleDragOver(index, e));
        row.addEventListener('drop', (e) => this.handleDrop(index, e));
        row.addEventListener('dragend', () => this.handleDragEnd());
      });
    },
    handleDragStart(index, event) {
      this.draggingIndex = index;
      if (event && event.dataTransfer) {
        event.dataTransfer.effectAllowed = 'move';
        event.dataTransfer.setData('text/plain', index);
      }
    },
    handleDragOver(index, event) {
      event.preventDefault();
      if (this.draggingIndex !== null && this.draggingIndex !== index) {
        const tableBody = this.$refs.sortTable.$el.querySelector('.el-table__body-wrapper tbody');
        if (tableBody) {
          const rows = tableBody.querySelectorAll('tr');
          rows.forEach((row, idx) => {
            if (idx === index) {
              row.classList.add('drag-over');
            } else {
              row.classList.remove('drag-over');
            }
          });
        }
      }
    },
    handleDrop(targetIndex, event) {
      event.preventDefault();
      if (this.draggingIndex === null || this.draggingIndex === targetIndex) {
        return;
      }
      const movingItem = this.topList.splice(this.draggingIndex, 1)[0];
      this.topList.splice(targetIndex, 0, movingItem);
      this.draggingIndex = targetIndex;
      
      // 清除拖拽样式
      const tableBody = this.$refs.sortTable.$el.querySelector('.el-table__body-wrapper tbody');
      if (tableBody) {
        const rows = tableBody.querySelectorAll('tr');
        rows.forEach((row) => {
          row.classList.remove('drag-over');
        });
      }
      
      // 重新初始化拖拽事件，因为 DOM 顺序已改变
      this.$nextTick(() => {
        this.initDragEvents();
      });
    },
    handleDragEnd() {
      this.draggingIndex = null;
      // 清除所有拖拽样式
      if (this.$refs.sortTable) {
        const tableBody = this.$refs.sortTable.$el.querySelector('.el-table__body-wrapper tbody');
        if (tableBody) {
          const rows = tableBody.querySelectorAll('tr');
          rows.forEach((row) => {
            row.classList.remove('drag-over');
          });
        }
      }
    },
    async handleSave() {
      if (!this.topList.length) {
        this.$message.warning('暂无需要保存的排序');
        return;
      }
      const payload = this.topList.map((item, index) => ({
        id: item.id,
        sortWeight: index,
      }));
      this.saving = true;
      try {
        const res = await apiCourse.updateTopCourseSort(payload);
        if (res.status === 200) {
          this.$message.success('排序更新成功');
          this.$emit('sorted');
          this.dialogVisible = false;
        } else {
          throw new Error(res.message || '排序更新失败');
        }
      } catch (error) {
        this.$message.error(error.message || '排序更新失败');
      } finally {
        this.saving = false;
      }
    },
    handleClosed() {
      this.topList = [];
      this.draggingIndex = null;
      this.loading = false;
      this.saving = false;
    },
    // 计算文本宽度（通过隐藏 span 获取实际宽度）
    getTextWidth(text = '') {
      if (typeof document === 'undefined') return 0;
      const span = document.createElement('span');
      span.innerText = text;
      span.style.cssText = 'position:absolute;visibility:hidden;font-size:14px;font-family:inherit;white-space:nowrap;';
      document.body.appendChild(span);
      const { width } = span.getBoundingClientRect();
      document.body.removeChild(span);
      return Math.ceil(width);
    },
    // 计算列宽（头+内容取最大值，加 padding，并控制最小值）
    calcColumnWidth(label, prop, padding = 24, min = 130, max = Infinity) {
      const contents = (this.topList || []).map(row => this.getTextWidth((row && row[prop]) || '-'));
      const maxContentWidth = contents.length ? Math.max(...contents) : 0;
      const labelWidth = this.getTextWidth(label || '');
      const baseWidth = Math.max(maxContentWidth, labelWidth) + padding;
      const clamped = Math.max(min, Math.min(baseWidth, max));
      return `${clamped}px`;
    },
  },
};
</script>

<style lang="scss" scoped>
.top-course-sorter {
  min-height: 200px;
  padding-top: 8px;
}

.top-course-sorter__table {
  ::v-deep .el-table__row {
    cursor: move;
    transition: background-color 0.2s ease;

    &:hover {
      background-color: #f9fbff;
    }

    &.is-dragging {
      opacity: 0.7;
      background-color: #ecf5ff;
    }

    &.drag-over {
      border-top: 2px solid #409eff;
    }
  }

  ::v-deep .el-table__body-wrapper {
    .el-table__row {
      &:last-child {
        .el-table__cell {
          border-bottom: none;
        }
      }
    }
  }

  ::v-deep .el-table__cell {
    padding: 12px 0;
  }
}

.drag-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: move;
  width: 100%;
  height: 100%;
  padding: 0 16px;

  i {
    font-size: 20px;
    color: #c0c4cc;
  }

  &:hover i {
    color: #409eff;
  }
}

.cell-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
}

.common-cell {
  font-weight: 400;
  font-size: 14px;
  color: #000000;
}

.dialog-footer {
  text-align: right;
}
</style>











