antdv Table组件展开行数据对齐表头(自定义表头)

1、需求如图:展开行里的数据要保持对齐表头,而且表头是可以自定义的(可自定义设置显示或者隐藏哪些字段),最好先看另一篇文章:antdv table组件封装成全局组件以及携带自定义表头展示

在这里插入图片描述

2、组件里使用公用表格组件,思路:表格嵌套表格,展开行里的表格展示的字段与外面表格保持一致,且不展示表头,其它不展示的内容赋值为空值,并且只显示一条数据即可!
// index.vue
<table-box
  v-if="isShow"
  :columns="state.columns"
  :dataSource="state.tableData"
  :pagination="pagination"
  :routerName="routerName"
  :rowSelection="rowSelection"
  @change="handleTableChange"
  @expand="handleExpanded"
  :expandedRowRender="expandedRowRender"
  @getTableColumns="getTableColumns"
>
  <template #showPostLabelList="{ record }">
    <span v-if="record.showPostLabelList && record.showPostLabelList.length > 0">
      <span>{{ record.showPostLabelList[0].name }}</span>
    </span>
    <span v-else>--</span>
  </template>
  <template #showIssueItem="{ record }">
    <span v-if="record.showIssueItem && record.showIssueItem.length > 0">
      <span>{{ record.showIssueItem[0].name }}</span>
    </span>
    <span v-else>--</span>
  </template>
  <template v-slot:expandedRowRender="{ record }">
    <div class="expand-box" v-if="record.tableShow">
      <a-table
        :showHeader="false"
        :columns="state.rowColumns"
        :data-source="record.innerData"
        :pagination="false"
        :row-key="(record) => record.id"
      >
        <template #showPostLabelList="{ record }">
          <div v-if="record.showPostLabelList && record.showPostLabelList.length > 1" class="row-item-box">
            <span class="row-item" v-for="item in record.showPostLabelList.slice(1, record.showPostLabelList.length)" :key="item">{{ item.name }}</span>
          </div>
          <span v-else>--</span>
        </template>
        <template #showIssueItem="{ record }">
          <div v-if="record.showIssueItem && record.showIssueItem.length > 1" class="row-item-box">
            <span class="row-item" v-for="item in record.showIssueItem.slice(1, record.showIssueItem.length)" :key="item">{{ item.name }}</span>
          </div>
          <span v-else>--</span>
        </template>
      </a-table>
    </div>
  </template>
  <template #action="{ record }">
    <a-popover title="">
      <template #content>
        <div
          class="action-box"
          style="display: flex; flex-direction: column"
        >
          <a @click="handleEdit(true, record)">修改</a>
          <a @click="handleDel(record.id)" href="javascript:void(0)"
            >删除</a
          >
        </div>
      </template>
      <MenuOutlined />
    </a-popover>
  </template>
</table-box>
<script setup>
const state = reactive({
  tableData: [],
  selectedRowKeys: [],
  columns: [
    {
      title: "类型名称",
      dataIndex: "typeName",
      key: "typeName",
      ellipsis: true,
    },
    {
      title: "简称",
      dataIndex: "abbreviation",
      key: "abbreviation",
      ellipsis: true,
    },
    {
      title: "协议接入",
      dataIndex: "agreement",
      key: "agreement",
      ellipsis: true,
    },
    {
      title: "标签类型",
      dataIndex: "labelType",
      key: "labelType",
      ellipsis: true,
    },
    {
      title: "上报监测项",
      dataIndex: "showPostLabelList",
      key: "showPostLabelList",
      slots: {
        customRender: "showPostLabelList",
      },
      ellipsis: true,
      width: 200
    },
    {
      title: "下发监测项",
      dataIndex: "showIssueItem",
      slots: {
        customRender: "showIssueItem",
      },
      key: "showIssueItem",
    },
    {
      key: "action",
      isSlot: true,
      slots: {
        customRender: "action",
      },
    }
  ],
  rowColumns: []
});
// 获取表格数据
const getTableData = (formData) => {
  for (let i = 0; i < 7; i++) {
    state.tableData.push({
      id: i,
      key: i,
      typeName: "窨井水位计",
      abbreviation: "窨井",
      agreement: "s651_5",
      showPostLabelList: [
        {
          id: 1,
          name: '泵机状态'
        },
        {
          id: 2,
          name: 'TOC'
        },
        {
          id: 3,
          name: '开机台数'
        }
      ],
      labelType: '泵机状态',
      showIssueItem: [
        {
          id: 1,
          name: '水温'
        },
        {
          id: 2,
          name: '水压'
        },
        {
          id: 3,
          name: '电压'
        }
      ],
    });
  }
  loading.value = false;
};
// 点击展开行
const handleExpanded = async (obj) => {
  if (obj.expanded) {
    let index = 0;
    state.tableData.forEach((t, i) => {
      t.id == obj.record.id ? (index = i) : "";
    });
    obj.record.innerData = await getDeviceData(); // 获取当前展开行表格数据,除了上报和下发监测项外,其它为空,且只有一行数据
    obj.record.tableShow = true;
  }
};
// 获取展开行的表格的表头数据
const getTableColumns = (data) => {
  state.rowColumns = data;
};
const getDeviceData = () => {
  let arr = [];
  for (let i = 1; i < 2; i++) {
    arr.push({
      id: i,
      key: i,
      typeName: "",
      abbreviation: "",
      agreement: "",
      showPostLabelList: [
        {
          id: 1,
          name: '泵机状态'
        },
        {
          id: 2,
          name: 'TOC'
        },
        {
          id: 3,
          name: '开机台数'
        }
      ],
      labelType: '',
      showIssueItem: [
        {
          id: 1,
          name: '水温'
        },
        {
          id: 2,
          name: '水压'
        },
        {
          id: 3,
          name: '电压'
        }
      ],
    });
  }
  return arr;
};
onMounted(async () => {
  if (
    sessionStorage.tableHeadObj &&
    JSON.parse(sessionStorage.tableHeadObj)[routerName.value]
  ) {
    let arr = JSON.parse(sessionStorage.tableHeadObj)[routerName.value];
    for (let i = 0; i < state.columns.length; i++) {
      if (arr.indexOf(state.columns[i].key) == -1) {
        state.columns[i].isShow = false;
      }
    }
    isShow.value = true;
  } else {
    isShow.value = true;
  }
  getTableData(formData);
});
</script>
3、表格公用组件修改: 把表头数据修改后传给父组件渲染展开行里的表格
// tableBox.vue
const emit = defineEmits(["change", "expand", "getTableColumns"]);
// 监听表头数据的变化,响应到展开行里的表头数据
watchEffect(() => {
  emit('getTableColumns', tableColumns.value);
})
const getTableColumns = () => {
  emit('getTableColumns', tableColumns.value)
}
let showColumns = createColumns();
showColumns = showColumns.filter((i) => i.isShow == true);
tableColumns.value = showColumns; // 表格显示的所有项,isShow 为true时
getTableColumns();
4、因为有展开行和选中的宽度,所以展开行里表格样式要稍微改一改哟
// index.vue
<style lang="less" scoped>
.deviceTypeManage {
  // 展开行表格的样式
  .expand-box {
    margin-left: 68px;
    .row-item-box {
      .row-item {
        display: flex;
        flex-direction: column;
        margin-bottom: 16px;
        &:last-child {
          margin-bottom: 0px;
        }
      }
    }
  }
  :deep(.ant-table-expanded-row td:nth-child(2)) {
    padding: 0px 16px;
    border: none;
  }
  :deep(.ant-table-expanded-row .ant-table) {
    background: #fbfbfb;
  }
}
</style>
5、完成,下次再也不用担心这些骚设计了,效果如图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、注意一点儿:后台返回的数据一般没有key属性的,因为在表格子组件展开行有使用到key值,所以请求回来的数据手动加key属性:
// 获取表格数据
const getTableData = (formData) => {
  loading.value = true;
  request(url.GET_DEVICE_STATUS_LIST, "get", {
    pageNum: pagination.current,
    pageSize: pagination.pageSize,
    ...formData,
  })
    .then(res => {
      state.selectedRowKeys = [];
      totalCount.value = res.count.total;
      inlineCount.value = res.count.onlineCount;
      offlineCount.value = res.count.offLineCount;
      state.tableData = res.page.rows.map(i => ({...i, key: i.id}));
      pagination.total = res.page.total;
    })
    .finally(() => {
      loading.value = false;
    })
};

向上的路并不拥挤,因为大部分人选择了安逸。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值