需求描述
页面初始化时加载table列表,默认列表数据的时间周期为空,多选框不可选择;在操作栏中点击添加按钮实现手动输入,输入完成默认勾选该条数据,多选框可选择、取消。
支持翻页勾选,以及当前页的全选、取消全选(对于全数据选择/取消需要后端全数据处理,不建议)。
实现方法
方法一
利用el-table的select、select-all事件;表格selection列的selectable属性进行操作,代码如下:
表格(弹框):
<el-dialog v-model="dialogFormVisible" title="选择" append-to-body draggable width="60%">
<div class="page-content">
<el-table :data="tableData" ref="tableRef" style="width: 100%" height="100%" border highlight-current-row header-row-class-name="header-table" @select="handleSelect" @select-all="handleSelectAll">
<el-table-column type="selection" width="55" :selectable="selectable"/>
<el-table-column prop="groupId" label="列一" align="center"/>
<el-table-column prop="groupName" label="列二" align="center"/>
<el-table-column prop="groupCycleDate" label="时间周期" min-width="180" align="center">
<template #default='scope'>
<span v-if="!scope.row.add">{{ scope.row.groupCycleDate }}</span>
<el-date-picker v-model="scope.row.groupCycleDateRange" type="datetimerange" range-separator="-" :default-time="defaultTime"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD HH:mm:ss" clearable v-else/>
</template>
</el-table-column>
<el-table-column label="操作" width="100" fixed='right' align="center">
<template #default='scope'>
<el-button type="primary" size="small" @click="changeDate(scope.row, true, '0')" link v-if="!scope.row.add">添加</el-button>
<div v-else>
<el-button size="small" @click="changeDate(scope.row, false, '1')" link>取消</el-button>
<el-button type="primary" size="small" @click="changeDate(scope.row, false, '2')" link>确认</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
<!-- 自行封装的分页组件 -->
<div class="page-footer">
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit" :loading="submitLoading">确 定</el-button>
<el-button @click="handleClose">取 消</el-button>
</div>
</template>
</el-dialog>
主要实现逻辑:
const dialogFormVisible = ref(false);
const submitLoading = ref(false);
const tableData = ref([]);
const tableRef = ref(null);
const allSelectedData = ref([]);
// 保存已填写时间的数据
const allTimeData = ref([]);
const tableLoading = ref(false);
const defaultTime = [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)];
// 是否可勾选
const selectable = (row, index) => {
return !!row.groupCycleDate;
}
// 用户手动勾选时触发
const handleSelect = (selection,row) => {
// selection: 当前页所有已选中的行数据(包括本次变化后的结果)
// row: 刚刚被操作(选中或取消)的那一行数据
console.log('selection', selection)
const selectedRowIds = new Set(allSelectedData.value.map(item => item.id))
if (selection.includes(row)) {
// 选中操作:如果该行不在全部选中集合中,则添加
if (!selectedRowIds.has(row.id)) {
allSelectedData.value.push(row)
}
} else {
// 取消选中操作:从全部选中集合中移除该行
const index = allSelectedData.value.findIndex(item => item.id === row.id)
if (index > -1) {
allSelectedData.value.splice(index, 1)
}
}
}
// 用户手动勾选全选框时触发
const handleSelectAll = (selection) => {
// selection: 当前页所有被选中的行数据(如果操作是取消全选,则为空数组),tableData只会包含当前页面的数据
const currentPageIds = tableData.value.map(row => row.id);
const selectedRowIds = new Set(allSelectedData.value.map(item => item.id));
if (selection.length > 0) {
// 全选当前页:将当前页尚未选中的项添加到总集合
selection.forEach(row => {
if (!selectedRowIds.has(row.id)) {
allSelectedData.value.push(row);
}
})
} else {
// 取消全选当前页:只从总集合中移除当前页的项
allSelectedData.value = allSelectedData.value.filter(
item => !currentPageIds.includes(item.id)
)
}
}
// 翻页勾选数据
const fetchTableData = async () => {
// 数据更新后,在nextTick中回显选中状态
nextTick(() => {
if (tableData.value && allSelectedData.value.length > 0) {
tableData.value.forEach(row => {
const isSelected = allSelectedData.value.some(
selected => selected.id === row.id
)
tableRef.value?.toggleRowSelection(row, isSelected);
})
}
})
}
// 列表查询
const getList = () => {
// 模拟数据
if (queryParams.value.pageNum == 2) {
tableData.value = [
{
id: '1-1-5',
groupId: '1562145875445',
groupName: '五',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-6',
groupId: '3562145875346',
groupName: '六',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-7',
groupId: '458745875447',
groupName: '七',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-8',
groupId: '32145145875448',
groupName: '八',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
}
];
} else {
tableData.value = [
{
id: '1-1-1',
groupId: '1562145875441',
groupName: '一',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-2',
groupId: '3562145875342',
groupName: '二',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-3',
groupId: '458745875443',
groupName: '三',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
},
{
id: '1-1-4',
groupId: '32145145875444',
groupName: '四',
groupCycleDate: '',
groupCycleDateRange: [],
add: false
}
];
}
tableData.value.forEach(item => {
item.groupCycleDate = '';
item.groupCycleDateRange = [];
const indexItem = allTimeData.value.findIndex(filled => filled.id === item.id);
if (indexItem > -1) {
item.groupCycleDate = allTimeData.value[indexItem].groupCycleDate;
item.groupCycleDateRange = allTimeData.value[indexItem].groupCycleDateRange;
}
});
fetchTableData();
}
// 确定
const submit = () => {
if (!allSelectedData.value.length) {
proxy.$modal.msgError('请选择要添加的群聊');
submitLoading.value = false;
return false;
}
console.log('params', params);
... // 其他业务逻辑
}
// 添加
const changeDate = (row, status,selection) => {
row.add = status;
const preCycleDate = row.groupCycleDate;
if (row?.groupCycleDateRange?.length) {
if (selection == '2') {
row.groupCycleDate = row.groupCycleDateRange.join('—');
toggleSelection([row], true);
} else if (selection == '1') {
const preCycleDateRange = [];
if (preCycleDate) {
preCycleDateRange.push(...preCycleDate.split('—'));
}
row.groupCycleDate = preCycleDate;
row.groupCycleDateRange = preCycleDateRange;
}
} else {
if (selection == '2') {
row.groupCycleDate = '';
toggleSelection([row],false);
}else if (selection == '1') {
const preCycleDateRange = [];
if (preCycleDate) {
preCycleDateRange.push(...preCycleDate.split('—'));
}
row.groupCycleDate = preCycleDate;
row.groupCycleDateRange = preCycleDateRange;
}
}
}
// 勾选
const toggleSelection = (rows,isSelected) => {
if (rows) {
rows.forEach((row) => {
tableRef.value.toggleRowSelection(row, isSelected);
if (isSelected) {
allSelectedData.value.push(row);
allTimeData.value.push(row);
}else {
allSelectedData.value = allSelectedData.value.filter(item => item.id !== row.id);
allTimeData.value = allTimeData.value.filter(item => item.id !== row.id);
}
})
}
}
方法二
基本原理与方法一中的实现逻辑一致。不同之处在于,使用el-table的row-key和reserve-selection属性,翻页时不用再使用fetchTableData方法重新进行过勾选,el-table会自动记录之前勾选的内容,翻页时会进行自动勾选。
需要注意的是此时select-all事件中的参数selection不再只是当前页中的内容,它包括所有页面已经勾选的数据,所以此处在做逻辑处理时,不用适用selection.length > 0进行判断,因为此时可能会有上一页或者下一页或者其他页码勾选的数据。
html代码:
...
<!-- 省略相同代码 -->
<el-table :data="tableData" ref="tableRef" style="width: 100%" height="100%" border highlight-current-row header-row-class-name="header-table" @select="handleSelect" @select-all="handleSelectAll" row-key="id">
<el-table-column type="selection" width="55" :selectable="selectable" :reserve-selection="true"/>
...
</el-table>
...
业务逻辑代码中删除fetchTableData方法,修改handleSelectAll方法,getList加载数据时无需再调用fetchTableData方法。
...
// 省略相同代码
// 用户手动勾选全选框时触发
const handleSelectAll = (selection) => {
// selection: 所有页被选中的行数据(如果没有选中的数据,则为空数组),tableData只会包含当前页面的数据
allSelectedData.value = [...selection];
}
// 删除fetchTableData方法
// 去除getList中的fetchTableData调用
const getList = () => {
...
// fetchTableData();
}
4609

被折叠的 条评论
为什么被折叠?



