项目要求:

实现一个左侧第一列为表头,且第一列所有单元格合并为一格的表格

最终效果图:

网上冲浪找了很多没有找到直接合并第一列整列的,表头跟内容设置合并是分开的。

只能换个思路实现:

把表头隐藏:

:showHeader="false"

然后列名再复写在第一行,第一列所有单元合并成为一格

以下是源码:

代码有点多,关键代码是:在构造表格内空时先把列名写在第一名。

this.dataSource.push(
    {
      projName: '项目',
      type: '产品线',
      key: '5',
      needTotal: 'NRE',
      actualTotal: '实现投入人力'

    })

然后是::showHeader="false" 设置表头隐藏。

<template>
  <div class="tabletest rowColor headBold firstgreen">
    ///带合并行的单元格功能表,根据内容来合并,并要求实现点击功能
    <div>
      <a-table bordered
               :columns="columns"
               :data-source="dataSource"
               :pagination="false"
               @load="loading"
               rowKey="id"
               :showHeader="false"
      ></a-table>
    </div>
    <br/>
    <br/>
  </div>
</template>
<script>
let ct = 0
export default {
  name: "AllProjectTable",
  data() {
    return {
      msg: "data-home",
      dataSource: [],
      countnum: 0,
      columns: [
        {
          title: '部门',
          dataIndex: 'count',
          key: 'count',
          customRender: (value, row, rowIndex) => { //只针对第一列
            // console.log('遍历value,row, index ,this.countnum,ct', value, row, index, this.countnum, ct);
            console.log('针对第一列进行合并操作')
            const obj = {
              children: '01项目',
              attrs: {},
            };
            if (rowIndex === 0) {   // 第一行数据开始,跨行合并的长度为数据data的长度
              obj.attrs.rowSpan = this.dataSource.length; // len表示该数据占几行:u01占4行,合并4行
            }
            if (1 <= rowIndex) {    // 从第一行往后的所有行表格均合并,0表格第二行以后的单元格不画
              obj.attrs.rowSpan = 0;
            }
      
            return obj;
          },
          customCell: (row, index) => {
            return {
              style: {
                'font-weight': 'bold' ,
                'background': 'rgba(0, 255, 120, 1)',
                'cursor': 'pointer',
                'width':'100px'
              },
              on: {
                click: (e) => {
                  console.log('点击事件,在第1列')
                  this.selectRow(row, index, 1);
                },
              },
            };
          },
        },
        {
          title: '产品线',
          dataIndex: 'type',
          key: 'type',
          customCell: (row, index) => {
            return {
              style: {'cursor': 'pointer'},
              on: {
                click: (e) => {
                  console.log('点击事件,在第2列')
                  this.selectRow(row, index, 2);
                },
              },
            };
          },
          customRender: (value, record, index) => {
            // return this.mergeColumn2Ok(value, row, rowIndex)
            console.log('针对第二列进行合并,执行OK', record, index, record.type)
            console.log('')
            const obj = {
              children: value,
              attrs: {},
            };
            let arr = this.dataSource.filter((res) => {
              //这里type是我需要判断的字段名(相同就合并)
              return res.type == record.type;
            });
            console.log('arr', arr)
            if (index === 0 || this.dataSource[index - 1].type != record.type) {
              console.log('rowspan index =', index)
              obj.attrs.rowSpan = arr.length;
            } else {
              console.log('rowspan is =0 , at=', index)
              obj.attrs.rowSpan = 0;
            }
            return obj;
          },

        },
        {
          title: '项目',
          dataIndex: 'projName',
          key: 'projName',
          customHeaderCell: () => ({
            style: {
              textAlign: 'center',  //头部单元格水平居中
            },
          }),
          customCell: (row, index) => {
            return {
              style: {'cursor': 'pointer'},
              on: {
                click: (e) => {
                  console.log('点击事件,在第3列')
                  this.selectRow(row, index, 3);
                },
              },
            };
          },
        },
        {
          title: 'NRE Total(人)',
          dataIndex: 'needTotal',
          key: 'needTotal',
          align: 'center',
        },
        {
          title: '实际投入人力',
          dataIndex: 'actualTotal',
          key: 'actualTotal',
        },
      ]
      ,
    };
  },
  mounted() {
    this.getData(null)
  },
  methods: {
    mergeColumn2Ok(value, row, rowIndex) {
      console.log('针对第二列进行合并,执行OK', row, rowIndex, row.type)
      const obj = {
        children: row.type,
        attrs: {},
      };
      if (rowIndex === 0) {   // 第一行数据开始,跨行合并的长度为数据data的长度
        obj.attrs.rowSpan = 2; // 合并当前列:第一行与第二行
      }
      if (1 === rowIndex) {    //0表示:当前列的第二行的单元格不画
        obj.attrs.rowSpan = 0;
      }
      return obj
    },
    selectRow(rowValue, rowIndex, columnIndex) {
      console.log('>>点击:第', rowIndex, '行 ', '第', columnIndex, '列, ', rowValue)
    },
    getRowClassName(record) {
      if (record.serial == this.serial) {
        return 'class-name'
      }
      return ''
    }
    ,
    getData: function (record) {
      let data = {}
      console.log(record)

      data = {
        "extend": {
          "KEY_DATA": {
            "VALUE_MAP": {
              "新业务": [
                {
                  "id": 2,
                  "projectName": "Se",
                  "projectStage": "NI",
                  "actualTotal": 3,
                  "nreTotal": 80
                }
              ],
              "Hearable": [
                {
                  "id": 7,
                  "projectName": "Ra",
                  "projectStage": "NPI",
                  "actualTotal": 0,
                  "nreTotal": 24
                }
              ],
              "Home": [
                {
                  "id": 1,
                  "projectName": "C4",
                  "projectStage": "NPI",
                  "actualTotal": 3,
                  "nreTotal": 50
                }
              ]
            }
          }
        }
      }
      this.dataSource = []
      this.dataSource.push(
          {
            projName: '项目',
            type: '产品线',
            key: '5',
            needTotal: 'NRE',
            actualTotal: '实现投入人力'

          })
      for (const key in data.extend.KEY_DATA.VALUE_MAP) {
        console.log('key', key)
        data.extend.KEY_DATA.VALUE_MAP[key].forEach(item => {
          let obj = {
            projName: item.projectName,
            type: key,
            key: key,
            needTotal: item.nreTotal,
            actualTotal: item.actualTotal
          }
          console.log('item=>', item)
          this.dataSource.push(obj)
        })
      }
      console.log(this.dataSource)
      return this.dataSource
    }
    ,

    loading() {
      this.countnum = 60
      console.log('-')
    }

  }
};
</script>
<style lang="less" scoped>
.tabletest {
  .title {
    font-size: 40px;
    letter-spacing: 2px;
  }
}

//a-table的父级盒子选择器 >>> 取消 表格鼠标移入的行 背景色样式
::v-deep .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td, .ant-table-row-hover, .ant-table-row-hover > td {
  background: none !important;
}

</style>

我这里源码还包括对第二列的内容相同的,进行动态合并。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐