fixed: Fixed an issue where the total number of cross-page multiple selections was the number of selected pages

This commit is contained in:
zhaojisen
2024-12-18 18:38:26 +08:00
committed by ZhaoJiSen
parent 4c61a84652
commit cb6e40bea7
2 changed files with 82 additions and 74 deletions

View File

@@ -7,7 +7,7 @@
<template v-else> <template v-else>
<el-table <el-table
ref="table" ref="table"
v-loading="loading" v-loading="tableLoading"
:data="data" :data="data"
:row-class-name="rowClassName" :row-class-name="rowClassName"
v-bind="tableAttrs" v-bind="tableAttrs"
@@ -749,7 +749,7 @@ export default {
page: defaultFirstPage, page: defaultFirstPage,
// https://github.com/ElemeFE/element/issues/1153 // https://github.com/ElemeFE/element/issues/1153
total: null, total: null,
loading: false, tableLoading: false,
// 多选项的数组 // 多选项的数组
selected: [], selected: [],
@@ -940,11 +940,11 @@ export default {
}, },
getListFromStaticData({ loading = true } = {}) { getListFromStaticData({ loading = true } = {}) {
if (loading) { if (loading) {
this.loading = true this.tableLoading = true
} }
if (!this.hasPagination) { if (!this.hasPagination) {
this.data = this.totalData this.data = this.totalData
this.loading = false this.tableLoading = false
if (this.isTree) { if (this.isTree) {
this.data = this.tree2Array(this.data, this.expandAll) this.data = this.tree2Array(this.data, this.expandAll)
} }
@@ -957,7 +957,7 @@ export default {
const end = (page + pageOffset) * this.size const end = (page + pageOffset) * this.size
this.$log.debug(`page: ${page}, size: ${this.size}, start: ${start}, end: ${end}`) this.$log.debug(`page: ${page}, size: ${this.size}, start: ${start}, end: ${end}`)
this.data = this.totalData.slice(start, end) this.data = this.totalData.slice(start, end)
this.loading = false this.tableLoading = false
this.data = this.tree2Array(this.data, this.expandAll) this.data = this.tree2Array(this.data, this.expandAll)
return this.data return this.data
}, },
@@ -983,7 +983,7 @@ export default {
queryUtil.stringify(query, '=', '&') queryUtil.stringify(query, '=', '&')
// 请求开始 // 请求开始
this.loading = loading this.tableLoading = loading
// 存储query记录, 便于后面恢复 // 存储query记录, 便于后面恢复
if (this.saveQuery) { if (this.saveQuery) {
@@ -1023,7 +1023,7 @@ export default {
this.total === 0 && this.total === 0 &&
(_isEmpty(formValue) || _values(formValue).every(isFalsey)) (_isEmpty(formValue) || _values(formValue).every(isFalsey))
this.loading = false this.tableLoading = false
/** /**
* 请求返回, 数据更新后触发 * 请求返回, 数据更新后触发
* @property {object} data - table的数据 * @property {object} data - table的数据
@@ -1043,7 +1043,7 @@ export default {
*/ */
this.$emit('error', err) this.$emit('error', err)
this.total = 0 this.total = 0
this.loading = false this.tableLoading = false
}) })
}, },
search(attrs, reset) { search(attrs, reset) {
@@ -1106,9 +1106,13 @@ export default {
this.page = val this.page = val
this.getList() this.getList()
}, },
handleSelectAll(e, canSelect) { handleSelectAll(selection, selectable = () => true) {
this.loading = true this.tableLoading = true
this.selectStrategy.onSelectAll(e, canSelect) try {
this.selectStrategy.onSelectAll(selection, selectable)
} finally {
this.tableLoading = false
}
}, },
/** /**
* 切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否 * 切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否

View File

@@ -53,102 +53,100 @@ class StrategyNormal extends StrategyAbstract {
class StrategyPersistSelection extends StrategyAbstract { class StrategyPersistSelection extends StrategyAbstract {
/** /**
* 批量处理表格选择状态 * 批量处理表格选择状态
* @param {Array} rows 需要处理的行数据
* @returns {Promise}
*/ */
batchProcessSelection(rows) { batchProcessSelection(rows) {
return new Promise((resolve) => { // 先清空当前页的选择状态
// 先清空当前页的选择状态 this.elTable.clearSelection()
this.elTable.clearSelection()
const batchSize = 50 // 直接处理当前页的选择状态
const batches = Math.ceil(rows.length / batchSize) rows.forEach(row => {
this.elTable.toggleRowSelection(row, true)
const processBatch = (batchIndex) => {
if (batchIndex >= batches) {
// 所有批次处理完成后关闭加载状态并resolve
this.elDataTable.loading = false
resolve()
return
}
const start = batchIndex * batchSize
const end = Math.min(start + batchSize, rows.length)
rows.slice(start, end).forEach(row => {
this.elTable.toggleRowSelection(row, true, false)
})
requestAnimationFrame(() => processBatch(batchIndex + 1))
}
requestAnimationFrame(() => processBatch(0))
}) })
} }
/**
* 处理选择变化事件
*/
onSelectionChange(val) {
const { id, data, selected } = this.elDataTable
// 如果当前页选中数量等于当前页数据量,说明是全选操作
const isSelectAll = val.length === data.length
if (isSelectAll) {
// 将当前页所有数据添加到 selected 中(如果还没有添加的话)
data.forEach(row => {
const foundIndex = selected.findIndex(r => r[id] === row[id])
if (foundIndex === -1) {
selected.push(row)
}
})
} else {
// 非全选情况:将不在 val 中的当前页数据从 selected 中移除
const selectedIds = new Set(val.map(r => r[id]))
data.forEach(row => {
const foundIndex = selected.findIndex(r => r[id] === row[id])
if (!selectedIds.has(row[id]) && foundIndex > -1) {
selected.splice(foundIndex, 1)
}
})
}
// 触发事件,传递所有选中的数据
this.elDataTable.$emit('selection-change', selected)
}
/** /**
* 用户切换某一行的多选 * 用户切换某一行的多选
*/ */
onSelect(selection, row) { onSelect(selection, row) {
const isChosen = selection.indexOf(row) > -1 const { id, selected } = this.elDataTable
const foundIndex = selected.findIndex(r => r[id] === row[id])
const isSelected = selection.includes(row)
this.toggleRowSelection(row, isChosen) if (isSelected && foundIndex === -1) {
selected.push(row)
} else if (!isSelected && foundIndex > -1) {
selected.splice(foundIndex, 1)
}
// 只更新这一行的选择状态
this.elTable.toggleRowSelection(row, isSelected)
this.elDataTable.$emit('selection-change', selected)
} }
/** /**
* 用户切换当前页的多选 * 用户切换当前页的多选
*/ */
onSelectAll(selection, selectable = () => true) { onSelectAll(selection, selectable = () => true) {
const { id, selected, data } = this.elDataTable const { id, selected, data } = this.elDataTable
// 获取可选择的行
const selectableRows = data.filter(selectable) const selectableRows = data.filter(selectable)
// 使用selection参数来判断是全选还是取消全选
const isSelected = selection.length > 0 const isSelected = selection.length > 0
if (isSelected) { if (isSelected) {
// 全选 // 将当前页所有可选择的数据添加到 selected 中
const rowsToAdd = selectableRows.filter(row => const rowsToAdd = selectableRows.filter(row =>
!selected.find(r => r[id] === row[id]) !selected.find(r => r[id] === row[id])
) )
selected.push(...rowsToAdd) selected.push(...rowsToAdd)
this.batchProcessSelection(selectableRows)
// 触发选择事件
rowsToAdd.forEach(row => {
this.elDataTable.$emit('toggle-row-selection', true, row)
})
} else { } else {
// 取消全选 // 从 selected 中移除当前页的数据
// 1. 先找出当前页面中已选中的行 selectableRows.forEach(row => {
const currentPageSelected = selectableRows.filter(row =>
selected.find(r => r[id] === row[id])
)
// 2. 从selected中移除这些行
currentPageSelected.forEach(row => {
const index = selected.findIndex(r => r[id] === row[id]) const index = selected.findIndex(r => r[id] === row[id])
if (index > -1) { if (index > -1) {
selected.splice(index, 1) selected.splice(index, 1)
} }
}) })
this.elTable.clearSelection()
// 3. 触发取消选择事件
currentPageSelected.forEach(row => {
this.elDataTable.$emit('toggle-row-selection', false, row)
})
} }
// 更新表格选择状态 this.elDataTable.$emit('selection-change', selected)
const selectedIds = new Set(selected.map(r => r[id]))
const currentPageSelectedRows = data.filter(r => selectedIds.has(r[id]))
return this.batchProcessSelection(currentPageSelectedRows)
} }
/** /**
* toggleRowSelection和clearSelection管理elDataTable的selected数组 * toggleRowSelection和clearSelection管理elDataTable的selected数组
* 记得最后要将状态同步到el-table中
*/ */
toggleRowSelection(row, isSelected) { toggleRowSelection(row, isSelected) {
const { id, selected } = this.elDataTable const { id, selected } = this.elDataTable
@@ -180,13 +178,19 @@ class StrategyPersistSelection extends StrategyAbstract {
const { data, id, selected } = this.elDataTable const { data, id, selected } = this.elDataTable
if (!this.elTable) { if (!this.elTable) {
return Promise.resolve() return
} }
const selectedIds = new Set(selected.map(r => r[id])) // 先清空当前页选择状态
const currentPageSelectedRows = data.filter(r => selectedIds.has(r[id])) this.elTable.clearSelection()
return this.batchProcessSelection(currentPageSelectedRows) // 只处理当前页的数据
data.forEach(row => {
const isSelected = selected.some(r => r[id] === row[id])
if (isSelected) {
this.elTable.toggleRowSelection(row, true)
}
})
} }
} }