先上效果:

 

 1.自定义表头:

通过设置 slot="header" 来自定义表头。 slot-scope="scope" 这一行千万不要因为没有再template中使用到scope,vscode报红而删除,这会导致input框不能输入任何内容!  

<template slot="header" slot-scope="scope">//slot-scope="scope" 千万不要因为vscode报红删除
  <el-row :gutter="2">
    <el-col :span="12">
      <el-form-item
        :label="`病案号${caseIndex + 1}:`"
        :prop="`data.${0}.patientList.${caseIndex}.bah`"
        :rules="tableRuleForm.bah"
      >
        <el-select
          v-model="caseItem.bah"
          value-key="brid"
          placeholder="请输入关键词并回车"
        >
          <el-option
            v-for="item in medicalOptions"
            :key="item.brid"
            :label="item.bah"
            :value="item"
          >
            <span>{{ item.brxm }}:{{ item.bah }}</span>
          </el-option>
        </el-select>
      </el-form-item>
    </el-col>
    <el-col :span="12">
      <el-form-item
        label="病人姓名:"
        :prop="`data.${0}.patientList.${caseIndex}.brxm`"
        :rules="tableRuleForm.brxm"
      >
        <el-input
          @change="$forceUpdate()"
          v-model="caseItem.brxm"
          size="mini"
          placeholder="请输入病人姓名"
        />
      </el-form-item>
    </el-col>
  </el-row>
</template>

2.多级表头和表头合并:

在 el-table-column 里面嵌套 el-table-column就可以实现多级表头。

<el-table-column
  prop="amount1"
  v-for="(caseItem, caseIndex) in tableData.data[0].patientList"
  :key="caseIndex"
>
  <el-table-column prop="amount1" label="完全符合">
    <el-table-column prop="amount1" align="center" width="80">
    </el-table-column>
  </el-table-column>
  <el-table-column prop="amount1" label="部分符合"
    ><el-table-column prop="amount1" align="center" width="80">
    </el-table-column>
  </el-table-column>
</el-table-column>

因为下边还有要操作的单元格,所以总符合率这里必须要将三列合并为一列。所以我们要找到需要合并的单元格位置,使用 .colSpan 属性来合并单元格,这里循环是因为table的列是动态添加的所以进行循环合并,如果是固定的列,就不需要循环,直接找到要合并的列就行了。setColSpan方法一定要等table的dom全部渲染完成了才可以调用!否则获取不到节点。我这里是放在mounted()函数中并设置了一个setTimeout用了300毫秒的延时调用。

// 合并表头
setColSpan() {
  // 获取第三行的多级表头
  let row = document
    .getElementsByClassName("is-group")[0]
    .getElementsByTagName("tr")[2];
  // console.log(row); //这里获取的表头排除了序号,检查项目,检查内容
  // 获取每一列
  let colAll = row.getElementsByTagName("th");
  // 循环列, .length -3 是减去序号,检查项目,检查内容这三列
  for (let index = 0; index < colAll.length - 3; index++) {
    if (index % 6 == 0) {
      // 只要当前列模以6是0就将本列加3(找到 不适用 下的这一列)的单元格的colSpan设为3
      row.getElementsByTagName("th")[index + 3].colSpan = 3;
      // 把接下来的两行设置为none 防止挤后边的
      row.getElementsByTagName("th")[index + 4].style.display = "none";
      row.getElementsByTagName("th")[index + 5].style.display = "none";
    }
  }
},

 3.行内容一致的跨行合并:

通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,第二个元素代表colspan。 也可以返回一个键名为rowspancolspan的对象。

<el-table
  :data="tableData.data"
  :span-method="objectSpanMethod"
  border
  height="calc(100vh - 280px)"
  style="width: 100%"
  class="table"
  >
</el-table>

 下边是方法

// 合并行
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  const dataProvider = this.tableData.data;
  if (columnIndex === 1) {
    const prevRow = dataProvider[rowIndex - 1]; //上一条数据
    let nextRow = dataProvider[rowIndex + 1]; //下一条数据
    // 如果上一条数据存在并且上一条数据和当前数据相同,那么就不渲染这个单元格
    if (prevRow && prevRow.BZMC === row.BZMC) {
      return { rowspan: 0, colspan: 0 };
      //不相同判断如何渲染
    } else {
      let rowspan = 1;
      // 如果下一条数据和当前数据相同那么应该合并单元格 while判断下边有几行和当前数据相同,while直到找到不相同的退出循环
      while (nextRow && nextRow.BZMC === row.BZMC) {
        rowspan++;
        // 只要当前行和下一行相同,那么对比rowspan加下一条数据是否相同
        nextRow = dataProvider[rowspan + rowIndex];
      }
      if (rowspan > 1) {
        return { rowspan, colspan: 1 };
      }
    }
  }
},

这里用while循环来判断到底进行多少次跨行合并。

4.table动态新增列的时候表格中间出现一大片空白,样式错乱

因为我这个table的列是动态新增的,在病案历数select框中我多选择一例就会新增病案号,病人姓名这几列。所以病案号是一个数组循环出来的列,我新增的时候push进去一个病人信息对象,table重新被渲染。渲染的时候table会闪一下然后出现一大片空白,如图:

具体原因不知道为什么,但是我猜测是因为我直接对渲染的table :data="tableData" 进行了操作导致的,所以我的解决方法是先拷贝一份当前渲染的tableData,操作拷贝的这个对象,最后先将tableData赋空,再把拷贝的对象赋值给tableData,这样就完美解决了。

changeCaseNum(value) {
  //深拷贝一份当前正在渲染的tableData进行操作
  let data = JSON.parse(JSON.stringify(this.tableData.data));
  if (data[0].patientList.length < value) {
    while (data[0].patientList.length < value) {
      data.forEach((item) => {
        item.patientList.push({
          fz: "100.00",
          bah: "",
          brxm: "",
          df: "0",
          wqfhs: data.length,
          bffhs: 0,
          bfhs: 0,
        });
      });
    }
  } else {
    data.forEach((item) => {
      item.patientList.splice(value);
    });
  }
  //先将当前渲染的talbeData 赋空
  this.tableData.data = [];
  //然后再将拷贝的data赋值给el-talbe渲染
  setTimeout(() => {
    this.tableData.data = data;
  });
  // 重新调用合并表头的方法
  setTimeout(() => {
    this.setColSpan();
  }, 300);
},

记得操作完table之后要重新调用 setColSpan()进行表头合并。

更多推荐