el-table表格持久化选择功能完善

<template>
  <div class="dual-table-container">
    <!-- 上方表格 - 已选中的数据 -->
    <div class="upper-table-section">
      <div class="section-header">
        <h3>已选中的数据</h3>
        <el-button type="primary" @click="handleSubmit" :disabled="upperTableData.length === 0">
          提交数据
        </el-button>
      </div>
      <el-table
        :data="upperTableData"
        border
        style="width: 100%"
        v-loading="upperTableLoading">
        <el-table-column prop="id" label="ID" width="80"></el-table-column>
        <el-table-column prop="name" label="名称" width="150"></el-table-column>
        <el-table-column prop="type" label="类型" width="120"></el-table-column>
        <el-table-column prop="description" label="描述"></el-table-column>
        <el-table-column label="操作" width="120" fixed="right">
          <template slot-scope="scope">
            <el-button
              type="danger"
              size="mini"
              @click="handleDeleteFromUpper(scope.row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 下方表格 - 可选数据 -->
    <div class="lower-table-section">
      <div class="section-header">
        <h3>可选数据</h3>
        <div class="header-controls">
          <el-tabs v-model="activeTab" @tab-click="handleTabChange">
            <el-tab-pane label="市场分析" name="market"></el-tab-pane>
            <el-tab-pane label="投资者" name="investor"></el-tab-pane>
          </el-tabs>
          <el-button type="success" @click="handleAddSelected" :disabled="selectedLowerData.length === 0">
            添加选中数据
          </el-button>
        </div>
      </div>
      
      <el-table
        ref="lowerTable"
        :data="lowerTableData"
        border
        style="width: 100%"
        v-loading="lowerTableLoading"
        @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column prop="id" label="ID" width="80"></el-table-column>
        <el-table-column prop="name" label="名称" width="150"></el-table-column>
        <el-table-column prop="type" label="类型" width="120"></el-table-column>
        <el-table-column prop="description" label="描述"></el-table-column>
      </el-table>
      
      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pagination.currentPage"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="pagination.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="pagination.total">
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DualTableDemo',
  data() {
    return {
      // 上方表格数据
      upperTableData: [],
      upperTableLoading: false,
      
      // 下方表格数据
      lowerTableData: [],
      lowerTableLoading: false,
      selectedLowerData: [], // 下方表格选中的数据
      
      // 当前激活的tab
      activeTab: 'market',
      
      // 分页配置
      pagination: {
        currentPage: 2, // 默认第二页
        pageSize: 10,
        total: 0
      },
      
      // 标记是否已经初始化过
      isInitialized: false,
      
      // 模拟数据 - 实际项目中应该从API获取
      mockData: {
        market: [
          { id: 1, name: '市场分析A', type: 'market', description: '这是市场分析数据A' },
          { id: 2, name: '市场分析B', type: 'market', description: '这是市场分析数据B' },
          { id: 3, name: '市场分析C', type: 'market', description: '这是市场分析数据C' },
          { id: 4, name: '市场分析D', type: 'market', description: '这是市场分析数据D' },
          { id: 5, name: '市场分析E', type: 'market', description: '这是市场分析数据E' },
          { id: 6, name: '市场分析F', type: 'market', description: '这是市场分析数据F' },
          { id: 7, name: '市场分析G', type: 'market', description: '这是市场分析数据G' },
          { id: 8, name: '市场分析H', type: 'market', description: '这是市场分析数据H' },
          { id: 9, name: '市场分析I', type: 'market', description: '这是市场分析数据I' },
          { id: 10, name: '市场分析J', type: 'market', description: '这是市场分析数据J' },
          { id: 11, name: '市场分析K', type: 'market', description: '这是市场分析数据K' },
          { id: 12, name: '市场分析L', type: 'market', description: '这是市场分析数据L' }
        ],
        investor: [
          { id: 101, name: '投资者A', type: 'investor', description: '这是投资者数据A' },
          { id: 102, name: '投资者B', type: 'investor', description: '这是投资者数据B' },
          { id: 103, name: '投资者C', type: 'investor', description: '这是投资者数据C' },
          { id: 104, name: '投资者D', type: 'investor', description: '这是投资者数据D' },
          { id: 105, name: '投资者E', type: 'investor', description: '这是投资者数据E' },
          { id: 106, name: '投资者F', type: 'investor', description: '这是投资者数据F' },
          { id: 107, name: '投资者G', type: 'investor', description: '这是投资者数据G' },
          { id: 108, name: '投资者H', type: 'investor', description: '这是投资者数据H' },
          { id: 109, name: '投资者I', type: 'investor', description: '这是投资者数据I' },
          { id: 110, name: '投资者J', type: 'investor', description: '这是投资者数据J' },
          { id: 111, name: '投资者K', type: 'investor', description: '这是投资者数据K' },
          { id: 112, name: '投资者L', type: 'investor', description: '这是投资者数据L' }
        ]
      }
    }
  },
  
  mounted() {
    this.loadLowerTableData()
  },
  
  methods: {
    // 加载下方表格数据
    async loadLowerTableData() {
      this.lowerTableLoading = true
      try {
        // 模拟API调用
        await this.$nextTick()
        const allData = this.mockData[this.activeTab]
        const startIndex = (this.pagination.currentPage - 1) * this.pagination.pageSize
        const endIndex = startIndex + this.pagination.pageSize
        
        this.lowerTableData = allData.slice(startIndex, endIndex)
        this.pagination.total = allData.length
        
        // 根据上方表格数据设置勾选状态
        this.$nextTick(() => {
          this.setSelectionByUpperData()
          // 只有在首次初始化且是市场分析tab的第二页时,才选中第2个数据并添加到上方表格
          if (!this.isInitialized && this.activeTab === 'market' && this.pagination.currentPage === 2) {
            this.selectDefaultItem()
            this.isInitialized = true
          }
        })
      } catch (error) {
        this.$message.error('加载数据失败')
        console.error('加载数据失败:', error)
      } finally {
        this.lowerTableLoading = false
      }
    },
    
    // 根据上方表格数据设置下方表格的勾选状态
    setSelectionByUpperData() {
      const upperIds = this.upperTableData.map(item => item.id)
      
      // 清空当前页面的所有选择
      this.$refs.lowerTable.clearSelection()
      
      // 根据上方表格数据设置勾选状态
      this.lowerTableData.forEach(row => {
        if (upperIds.includes(row.id)) {
          this.$refs.lowerTable.toggleRowSelection(row, true)
        }
      })
      
      // 更新选中数据数组,只包含当前页面被勾选的数据
      this.selectedLowerData = this.lowerTableData.filter(row => upperIds.includes(row.id))
    },
    
    // Tab切换处理
    handleTabChange() {
      this.pagination.currentPage = 1
      this.selectedLowerData = []
      this.isInitialized = false // 切换tabs时重置初始化标记
      this.loadLowerTableData()
    },
    
    // 分页大小改变
    handleSizeChange(size) {
      this.pagination.pageSize = size
      this.pagination.currentPage = 1
      this.selectedLowerData = []
      this.isInitialized = false // 改变分页大小时重置初始化标记
      this.loadLowerTableData()
    },
    
    // 当前页改变
    handleCurrentChange(page) {
      this.pagination.currentPage = page
      this.selectedLowerData = []
      this.loadLowerTableData()
    },
    
    // 下方表格选择变化
    handleSelectionChange(selection) {
      // 记录之前的选择状态
      const previousSelection = this.selectedLowerData
      this.selectedLowerData = selection
      
      // 如果是初始化后的手动操作,不自动添加到上方表格
      // 只有通过"添加选中数据"按钮才能添加到上方表格
    },
    

    

    
    // 添加数据到上方表格的通用方法
    addToUpperTable(dataArray) {
      if (!dataArray || dataArray.length === 0) return
      
      // 过滤掉已经在上方表格中的数据
      const upperIds = this.upperTableData.map(item => item.id)
      const newData = dataArray.filter(item => !upperIds.includes(item.id))
      
      if (newData.length > 0) {
        this.upperTableData = [...this.upperTableData, ...newData]
      }
    },
    
    // 添加选中数据到上方表格
    handleAddSelected() {
      if (this.selectedLowerData.length === 0) {
        this.$message.warning('请先选择要添加的数据')
        return
      }
      
      this.addToUpperTable(this.selectedLowerData)
      this.$message.success(`成功添加 ${this.selectedLowerData.length} 条数据`)
    },
    
    // 从上方表格删除数据
    handleDeleteFromUpper(row) {
      this.$confirm('确定要删除这条数据吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const index = this.upperTableData.findIndex(item => item.id === row.id)
        if (index > -1) {
          this.upperTableData.splice(index, 1)
          this.$message.success('删除成功')
          
          // 更新下方表格的勾选状态
          this.$nextTick(() => {
            this.setSelectionByUpperData()
          })
          
          // 从选中数据数组中移除被删除的数据
          this.selectedLowerData = this.selectedLowerData.filter(item => item.id !== row.id)
        }
      }).catch(() => {
        // 用户取消删除
      })
    },
    
    // 默认选中第二页的第2个数据
    selectDefaultItem() {
      // 确保在第二页且是市场分析tab
      if (this.activeTab === 'market' && this.pagination.currentPage === 2 && this.lowerTableData.length > 0) {
        // 选中第2个数据(索引为1)
        const targetIndex = 1
        if (this.lowerTableData[targetIndex]) {
          this.$refs.lowerTable.toggleRowSelection(this.lowerTableData[targetIndex], true)
          // 更新选中数据数组
          this.selectedLowerData = [this.lowerTableData[targetIndex]]
          // 初始化时自动添加到上方表格
          this.addToUpperTable([this.lowerTableData[targetIndex]])
        }
      }
    },
    
    // 提交数据
    handleSubmit() {
      if (this.upperTableData.length === 0) {
        this.$message.warning('请先添加数据')
        return
      }
      
      this.$confirm(`确定要提交 ${this.upperTableData.length} 条数据吗?`, '确认提交', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info'
      }).then(() => {
        // 这里可以调用实际的提交API
        console.log('提交的数据:', this.upperTableData)
        this.$message.success('数据提交成功')
        
        // 清空上方表格数据
        this.upperTableData = []
        
        // 更新下方表格的勾选状态
        this.$nextTick(() => {
          this.setSelectionByUpperData()
        })
      }).catch(() => {
        // 用户取消提交
      })
    }
  }
}
</script>

<style scoped>
.dual-table-container {
  padding: 20px;
}

.upper-table-section {
  margin-bottom: 30px;
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
}

.lower-table-section {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.section-header h3 {
  margin: 0;
  color: #333;
  font-size: 18px;
  font-weight: 600;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 20px;
}

.pagination-container {
  margin-top: 20px;
  text-align: center;
}

/* 表格样式优化 */
.el-table {
  margin-bottom: 10px;
}

.el-table th {
  background-color: #f5f7fa;
  color: #606266;
  font-weight: 600;
}

.el-table td {
  padding: 12px 0;
}

/* 按钮样式 */
.el-button {
  border-radius: 4px;
}

.el-button--primary {
  background-color: #409eff;
  border-color: #409eff;
}

.el-button--success {
  background-color: #67c23a;
  border-color: #67c23a;
}

.el-button--danger {
  background-color: #f56c6c;
  border-color: #f56c6c;
}

/* Tabs样式 */
.el-tabs__header {
  margin-bottom: 0;
}

.el-tabs__nav-wrap {
  margin-bottom: 0;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .section-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 15px;
  }
  
  .header-controls {
    width: 100%;
    justify-content: space-between;
  }
}
</style>

 

posted @ 2025-07-18 14:59  夏小夏吖  阅读(19)  评论(0)    收藏  举报