el-table 手动选择展示列

发布于:2025-03-05 ⋅ 阅读:(136) ⋅ 点赞:(0)
需求:

由于表格的列过多,用滚动条进行滚动对比数据不方便,所以提出,手动选择展示列

实现思路:
  1. 表格默认展示所有字段,每个字段通过 v-if 属性来进行判断是否显示;
  2. 点击设置按钮图标(表格右上角),弹出选择框el-popover;
  3. 选择框中包括:全选复选框、所有字段复选框组 el-checkbox-group、取消按钮、确定按钮;
  4. 选择展示字段后,点击“确定”按钮:更新每个字段值的show属性(true / false);
  5. 关闭弹出框;重新渲染表格;
  6. 选择展示字段后,点击“取消”按钮:关闭弹出框;
  7. 打开弹出框时:选中当前表格所展示的字段;重新渲染表格;
开发时遇到的坑点: 

打开和确定操作后,需要重新渲染表格:

// 重新渲染表格
    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();
    })
}
效果: