需求:
由于表格的列过多,用滚动条进行滚动对比数据不方便,所以提出,手动选择展示列
实现思路:
- 表格默认展示所有字段,每个字段通过 v-if 属性来进行判断是否显示;
- 点击设置按钮图标(表格右上角),弹出选择框el-popover;
- 选择框中包括:全选复选框、所有字段复选框组 el-checkbox-group、取消按钮、确定按钮;
- 选择展示字段后,点击“确定”按钮:更新每个字段值的show属性(true / false);
- 关闭弹出框;重新渲染表格;
- 选择展示字段后,点击“取消”按钮:关闭弹出框;
- 打开弹出框时:选中当前表格所展示的字段;重新渲染表格;
开发时遇到的坑点:
打开和确定操作后,需要重新渲染表格:
// 重新渲染表格
nextTick(() => {
tableRef.value.doLayout();
})
具体实现代码:vue3为例
html部分
//设置按妞点击打开选择框
<el-popover :visible="popoverVisible" :width="160" @show="showPopover">
<div class="popoverCheckBoxArea">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
<div style="margin: 10px 0;"></div>
<el-checkbox-group v-model="checkedColumns" @change="handleCheckedColumnsChange">
<el-checkbox v-for="column in columns" :label="column.lable" :key="column.lable">{{column.lable}}</el-checkbox>
</el-checkbox-group>
</div>
<div style="text-align: right; margin: 10px 0 0 0">
<el-button size="small" text @click="popoverVisible = false" style="margin-right: 10px;">取消</el-button>
<el-button size="small" type="primary" @click="confirmPopover ">
确定
</el-button>
</div>
<template #reference>
<el-button :icon="Setting" circle style="float: right;" @click="popoverVisible = true"/>
</template>
</el-popover>
//表格部分
<el-table v-loading="data.loading" @selection-change="handleSelectionChange" class="list-table"
:data="data.dataList" border stripe highlight-current-row ref="tableRef">
<el-table-column type="selection" width="45" align="center" />
<el-table-column label="#" align="center" type="index" width="60"/>
<el-table-column prop="code" label="服务器名称" align="center" width="140" v-if="showColumn('服务器名称')"/>
<!-- <el-table-column prop="interIp" label="内网IP" width="120" align="center" /> -->
<el-table-column prop="hostName" label="域名" align="center" width="200" v-if="showColumn('域名')">
<template #default="scope">
<el-tooltip class="box-item" effect="dark" :content="scope.row.interIp" placement="top">
{{ scope.row.hostName }}
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="isDeploy" label="是否部署" align="center" width="85" v-if="showColumn('是否部署')">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IS_DEPLOYMENT" :value="scope.row.isDeploy" :projectId="queryParams.projectId" />
</template>
</el-table-column>>
<el-table-column prop="httpPort" label="HTTP" align="center" width="60px" v-if="showColumn('HTTP')"/>
<el-table-column prop="socketPort" label="SOCKET" align="center" width="68px" v-if="showColumn('SOCKET')"/>
<el-table-column prop="operationType" label="状态" align="center" width="90px" v-if="showColumn('状态')">
<template #default="scope">
<el-tag v-if="scope.row.operationType != undefined" :type="operationTypecolor(scope.row.operationType)"
:effect="scope.row.operationType == '未知' ? 'light' : 'dark'">{{ scope.row.operationType }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="gsVer" label="当前版本" align="center" width="130px" v-if="showColumn('当前版本')"/>
<el-table-column prop="gsVerUpdateTime" label="上次更新时间" width="160" align="center" :formatter="(dateFormatter as any)" v-if="showColumn('上次更新时间')"/>
<el-table-column prop="publish" label="正式服" align="center" width="85px" v-if="showColumn('正式服')">
<template #default="scope">
<dict-tag :type="DICT_TYPE.FORMALDRESS" :value="scope.row.publish" :projectId="queryParams.projectId" />
</template>
</el-table-column>>
<el-table-column prop="showTime" label="展示时间" width="160" align="center" :formatter="(dateFormatter as any)" v-if="showColumn('展示时间')"/>
<el-table-column prop="startTime" label="开服时间" width="95" align="center" :formatter="dateFormatters" v-if="showColumn('开服时间')"/>
<el-table-column prop="mergeTime" label="合服时间" width="95" align="center" :formatter="dateFormatters" v-if="showColumn('合服时间')"/>
<el-table-column prop="mergeCount" label="合服次数" width="81" align="center" v-if="showColumn('合服次数')"/>
<el-table-column prop="gsFrontVersion" label="前端版本" width="100" align="center" v-if="showColumn('前端版本')"/>
<el-table-column prop="serviceDays" label="开服天数" width="100" align="center" v-if="showColumn('开服天数')"/>
<el-table-column prop="gsLevel" label="游戏服等级" width="100" align="center" v-if="showColumn('游戏服等级')"/>
<el-table-column prop="s_type" label="执行区" width="100" align="center" fixed="right">
<template #default="scope">
<div style="display: flex;">
<span class="readoDiv" v-if="scope.row.s_type != undefined" :style="color(scope.row.s_type)"></span>
<span class="readoSpan">{{ scope.row.s_type }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="110px" align="center" v-auth="['operation:gameserver:handleServiceList']" fixed="right">
<template #default="scope">
<el-dropdown ref="dropdown" trigger="click" @command="(command) => handleCommand(command, scope.row)"
v-auth="[
'operation:gameserver:handleServiceList',
]" @visible-change="visiblechange">
<el-button type="primary" link>
<Icon icon="ep:d-arrow-right" />>> 更多
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-popconfirm title="查看运行状态?" v-auth="'operation:gameserver:handleServiceList'"
@confirm="runningState(scope.row)" confirm-button-text="确定" cancel-button-text="取消" @show="show">
<template #reference>
<el-button :disabled="dropdowndisabled">
运行状态
</el-button>
</template>
</el-popconfirm>
<el-popconfirm title="查看关闭游戏?" v-auth="'operation:gameserver:handleServiceList'"
@confirm="closeGames(scope.row)" confirm-button-text="确定" cancel-button-text="取消" @show="show">
<template #reference>
<el-button :disabled="dropdowndisabled">
关闭游戏
</el-button>
</template>
</el-popconfirm>
<el-popconfirm title="查看启动游戏?" v-auth="'operation:gameserver:handleServiceList'"
@confirm="startGames(scope.row)" confirm-button-text="确定" cancel-button-text="取消" @show="show">
<template #reference>
<el-button :disabled="dropdowndisabled">
启动游戏
</el-button>
</template>
</el-popconfirm>
<el-popconfirm title="查看热更游戏?" v-auth="'operation:gameserver:handleServiceList'"
@confirm="watchGames(scope.row)" confirm-button-text="确定" cancel-button-text="取消" @show="show">
<template #reference>
<el-button :disabled="dropdowndisabled">
热更游戏
</el-button>
</template>
</el-popconfirm>
<el-dropdown-item command="updateGames" style="padding: 0; width: 100%;"
v-auth="'operation:gameserver:handleServiceList'" :disabled="dropdowndisabled">
<el-button :disabled="dropdowndisabled">
更新游戏
</el-button>
</el-dropdown-item>
<el-dropdown-item command="startFile" :disabled="dropdowndisabled">
<el-button :disabled="dropdowndisabled">
更新start文件
</el-button>
</el-dropdown-item>
<el-dropdown-item command="configFile" :disabled="dropdowndisabled">
<el-button :disabled="dropdowndisabled">
更新config文件
</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>
js部分
const popoverVisible = ref(false)
const checkAll = ref(true)
// 选择展示的字段数组默认的
const columns = ref([
{ lable: '服务器名称', show: true },
{ lable: '域名', show: true },
{ lable: '是否部署', show: true },
{ lable: 'HTTP', show: true },
{ lable: 'SOCKET', show: true },
{ lable: '状态', show: true },
{ lable: '当前版本', show: true },
{ lable: '上次更新时间', show: true },
{ lable: '正式服', show: true },
{ lable: '展示时间', show: true },
{ lable: '开服时间', show: true },
{ lable: '合服时间', show: true },
{ lable: '合服次数', show: true },
{ lable: '前端版本', show: true },
{ lable: '开服天数', show: false },
{ lable: '游戏服等级', show: false },
])
const checkedColumns:any = ref([]) //选中的数据
const isIndeterminate = ref(false)
// 点击弹出框的“全选”按钮
const handleCheckAllChange = (val:any)=> {
let columnsValueList:any = [];
columns.value.map(item => columnsValueList.push(item.lable));
checkedColumns.value = val ? columnsValueList : [];
isIndeterminate.value = false;
}
// 点击弹出框的选择展示菜单的复选框
const handleCheckedColumnsChange=(value:any) =>{
let checkedCount = value.length;
checkAll.value = checkedCount === columns.value.length;
isIndeterminate.value = checkedCount > 0 && checkedCount < columns.value.length;
}
//表格实例
const tableRef:any = ref(null)
// 弹出框打开时触发
const showPopover =()=> {
// 选中目前已展示的字段值
checkedColumns.value = [];
columns.value.map((item:any) => {
if(item.show) {
checkedColumns.value.push(item.lable);
}
});
// 如果目前展示的是全部字段,则需要勾选上“全选”按钮
if(columns.value.length == checkedColumns.value.length) {
checkAll.value = true;
isIndeterminate.value = false;
}
// 重新渲染表格
nextTick(() => {
tableRef.value.doLayout();
})
}
// 表格列是否显示的方法
const showColumn = (currentColumn:string)=>{
const column = columns.value.find((item: any) => item.lable === currentColumn);
if (column) {
return column.show;
} else {
console.error(`Column with label "${currentColumn}" not found.`);
return undefined; // 或者您可以选择抛出一个错误
}
}
// 点击弹出框的“确定”按钮
const confirmPopover = ()=> {
//选择不能没有,需要可放开注释
// if(checkedColumns.value.length == 0) {
// ElMessage.error('请选择需要展示的表格字段')
// return;
// }
// 根据选择结果,遍历修改列是否展示的属性值
columns.value.forEach(item => {
if(checkedColumns.value.some((el:any) => el == item.lable)) {
item.show = true;
} else {
item.show = false;
}
})
popoverVisible.value = false;
// 重新渲染表格
nextTick(() => {
tableRef.value.doLayout();
})
}