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>
是我吖~

浙公网安备 33010602011771号