el-table合并部分成功部分不成功?

要实现同图片所示内容,前4列内容都是固定的。
渲染代码如下
<template>
<div>
<el-table :data="waterData" border :span-method="handleSpanM">

                                <el-table-column align="center" width="65"><template slot-scope="scope">{{scope.row.name }}</template></el-table-column>
                                <el-table-column align="center" width="70" label="系数">
                                    <template slot-scope="scope"><el-input size="mini" class="" v-model="scope.row.factor"></el-input></template>
                                </el-table-column>
                                <el-table-column align="center" width="120" label="等级分数">
                                    <template slot-scope="scope"><el-input size="mini" v-model="scope.row.grade"></el-input></template>
                                </el-table-column>
                                <el-table-column align="center" width="180" label="符号选择">
                                    <template slot-scope="scope">
                                        <div class="symbol">
                                            <span style="display: none;">{{ scope.row.symbol }}</span>
                                            <span class="symbol_range"></span>
                                        </div>
                                    </template>
                                </el-table-column>
                                <el-table-column width="120" v-for="(column,index) in 6"  :key="`column-${index}`" ><template slot="header" slot-scope="scope"><div><el-input  size="small" v-model="waterForm[`water${index + 1}_label`]" ></el-input>  </div>  </template> <template slot-scope="scope"><div><el-input  size="small" v-model="waterForm[`water${index + 1}_factor`]" ></el-input></div> </template></el-table-column> </div></template>

<script>
export default {
data() {

return {
    tableData:[
        {name:'降水(mm)',factor:'0.7',grade:'',symbol: '1','':'','':'','':'','':'','':'','':''},
        {name:'降水(mm)',factor:'0.7',grade:'',symbol: '1','':'','':'','':'','':'','':'','':''},
        {name:'降水(mm)',factor:'0.7',grade:'',symbol: '1','':'','':'','':'','':'','':'','':''},
        {name:'降水(mm)',factor:'0.7',grade:'',symbol: '1','':'','':'','':'','':'','':'','':''},
        {name:'风速(m/s)',factor:'0.5',grade:'',symbol: '0','':'','':'','':'','':'','':'','':''},
        {name:'风速(m/s)',factor:'0.5',grade:'',symbol: '0','':'','':'','':'','':'','':'','':''},
        {name:'风速(m/s)',factor:'0.5',grade:'',symbol: '0','':'','':'','':'','':'','':'','':''},
        {name:'风速(m/s)',factor:'0.5',grade:'',symbol: '0','':'','':'','':'','':'','':'','':''},
    ],
    colFields:['name','factor','grade','symbol','','','','','',''],
    spanArr:[],waterForm:{}, };

},
methods: {

getSpanArr() {
  for (let i = 0; i < this.tableData.length; i++) {
    let row = i;
    // let col = i % this.colCount;
    if (row === 0) {
      // i 表示行 j表示列
      for (let j = 0; j < this.colFields.length; j++) {
        this.spanArr[i * this.colFields.length + j] = {
          rowspan: 1,
          colspan: 1,
        };
      }
    } else {
      for (let j = 0; j < this.colFields.length; j++) {
        if (
          this.colFields[j] == "name" ||
          this.colFields[j] == "factor" ||
          this.colFields[j] == "symbol"
        ) { // 指定合并哪些列
        /*this.tableData[row]["School"] !==
              this.tableData[row - 1]["School"]*/
          if (
            this.tableData[row][this.colFields[j]] !==
              this.tableData[row - 1][this.colFields[j]]
          ) { // 哪些不合并:School不一样的,不合并
            this.spanArr[row * this.colFields.length + j] = {
              rowspan: 1,
              colspan: 1,
            };
          } else if (
            this.tableData[row][this.colFields[j]] ===
            this.tableData[row - 1][this.colFields[j]]
          ) {
            let beforeItem =
              this.spanArr[(row - 1) * this.colFields.length + j];
            this.spanArr[row * this.colFields.length + j] = {
              rowspan: 1 + beforeItem.rowspan,// 合并几列
              colspan: 1,// 合并几行
            };
            beforeItem.rowspan = 0;
            beforeItem.colspan = 0;
          } else {
            // rowspan 和 colspan 都为1表格此单元格不合并
            this.spanArr[row * this.colFields.length + j] = {
              rowspan: 1,
              colspan: 1,
            };
          }
        }
      }
    }
  }
  // 对数据进行倒序
  let stack = [];
  for (let i = 0; i < this.colFields.length; i++) {
    for (let j = 0; j < this.tableData.length; j++) {
      // console.log("i=" + i + " j=" + j);
      // i 表示列 j表示行
      if (j === 0) {
        if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {
          stack.push(this.spanArr[j * this.colFields.length + i]);
        }
      } else {
        if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {
          stack.push(this.spanArr[j * this.colFields.length + i]);
        } else {
          stack.push(this.spanArr[j * this.colFields.length + i]);
          while (stack.length > 0) {
            let pop = stack.pop();
            let len = stack.length;
            this.spanArr[(j - len) * this.colFields.length + i] = pop;
          }
        }
      }
    }
  }
  // console.log(this.spanArr);
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
    return this.spanArr[rowIndex * this.colFields.length + columnIndex];
},}

},
mounted() {

this.getSpanArr();

},
渲染后结果image.png 怎么实现效果呢前4列除了第一列和第4列不可编辑其他都是可编辑的(输入框样式的,后面的表头也设置成可编辑的了)

系统能实现效果内容,现在发现第4列怎么都不合并。

阅读 2.6k
avatarAI BotBETA

为了解答您的问题并实现期望的表格合并效果,我们需要对您的 span-method 函数进行调整。另外,您提到第4列(即“符号选择”列)不应该合并,而其他列(除了第一列)在相同的数据值下应该合并。

以下是调整后的 getSpanArr 方法以及如何使用它来定义 span-method。请注意,我已经去掉了之前方法中的一些复杂逻辑,因为这不是必需的,而且可能导致合并行为出错。

methods: {
  getSpanArr() {
    const colFields = this.colFields;
    for (let rowIndex = 0; rowIndex < this.tableData.length; rowIndex++) {
      for (let colIndex = 0; colIndex < colFields.length; colIndex++) {
        if (rowIndex === 0) {
          this.spanArr[rowIndex * colFields.length + colIndex] = {
            rowspan: 1,
            colspan: 1,
          };
        } else {
          // 判断是否合并,只针对非第一列和第四列
          if (colIndex !== 0 && colIndex !== 3) {
            // 检查当前列的数据是否与前一行相同
            if (
              this.tableData[rowIndex][colFields[colIndex]] ===
              this.tableData[rowIndex - 1][colFields[colIndex]]
            ) {
              // 合并,获取前一行的合并配置,并更新
              let previousItemSpan = this.spanArr[(rowIndex - 1) * colFields.length + colIndex];
              if (previousItemSpan.rowspan > 1) {
                // 如果前一行已经合并了,则不需要再增加rowspan
                this.spanArr[rowIndex * colFields.length + colIndex] = {
                  rowspan: 0, // 设置为0表示此单元格将被上一行合并
                  colspan: 1,
                };
              } else {
                // 否则,更新rowspan
                previousItemSpan.rowspan++;
                this.spanArr[rowIndex * colFields.length + colIndex] = {
                  rowspan: 0,
                  colspan: 1,
                };
              }
            } else {
              // 不合并,设置默认配置
              this.spanArr[rowIndex * colFields.length + colIndex] = {
                rowspan: 1,
                colspan: 1,
              };
            }
          } else {
            // 第一列和第四列不合并,设置默认配置
            this.spanArr[rowIndex * colFields.length + colIndex] = {
              rowspan: 1,
              colspan: 1,
            };
          }
        }
      }
    }
  },
  objectSpanMethod({ row, column, rowIndex, columnIndex }) {
    if (this.spanArr.length) {
      return this.spanArr[rowIndex * this.colFields.length + columnIndex];
    }
  },
  // ... 其他方法
},
mounted() {
  this.getSpanArr();
},

此外,请确保在模板中正确地调用了 span-method

<el-table :data="tableData" border :span-method="objectSpanMethod">
  <!-- ... 其他列配置 ... -->
</el-table>

请注意,我已经将 span-method 绑定到 objectSpanMethod 方法上,并且使用 tableData 而不是 waterData(根据您的代码示例,我假设这是您想要的数据数组)。同时,我已经去掉了 colCount 的引用,因为它在您的代码中并未定义,并且我们直接使用 colFields.length 来确定列数。

最后,关于您提到的第4列(即“符号选择”列)的输入框样式,由于您已经使用了一个 <el-input> 组件,它默认就是可编辑的。如果您想要进一步自定义样式或行为,您可以在该组件上添加更多属性或样式类。

对于后面的表头,您已经使用 v-model 绑定到了 waterForm 对象上,这意味着这些表头也是可编辑的。如果您想要进一步自定义这些表头的行为或样式,您可以在模板中添加更多的逻辑或样式类。

1 个回答

先看下效果图:
image.png

<template></template>内容没变,waterData保留你的数据,只是使用了新的表格合并方法,你可以参考

export default {
   data() {
     return {
        waterData: [...],
        companyArr: [],
      companyPos: 0,
      simpleArr: [],
      simplePos: 0,
      symbolArr: [],
      symbolPos: 0,
     }
   },
   created() {
     this.merge(this.waterData)
   },
   methods: {
     // 表格行合并方法
    merge(tableData) {
      // 要合并的数组的方法
      this.companyArr = [];
      this.companyPos = 0;
      this.simpleArr = [];
      this.simplePos = 0;
      this.symbolArr = [];
      this.symbolPos = 0;
      for (var i = 0; i < tableData.length; i++) {
        if (i === 0) {
          // 第一行必须存在
          this.companyArr.push(1);
          this.companyPos = 0;
          this.simpleArr.push(1);
          this.simplePos = 0;
          this.symbolArr.push(1);
          this.symbolPos = 0;
        } else {
          // 第一列
          if (tableData[i].name === tableData[i - 1].name) {
            this.companyArr[this.companyPos] += 1;
            this.companyArr.push(0);
          } else {
            this.companyArr.push(1);
            this.companyPos = i;
          }

          // 第二列
          if (
            tableData[i].name === tableData[i - 1].name &&
            tableData[i].factor === tableData[i - 1].factor
          ) {
            this.simpleArr[this.simplePos] += 1;
            this.simpleArr.push(0);
          } else {
            this.simpleArr.push(1);
            this.simplePos = i;
          }

          // 第四列
          if (
            tableData[i].name === tableData[i - 1].name &&
            tableData[i].factor === tableData[i - 1].factor &&
            tableData[i].symbol === tableData[i - 1].symbol
          ) {
            this.symbolArr[this.symbolPos] += 1;
            this.symbolArr.push(0);
          } else {
            this.symbolArr.push(1);
            this.symbolPos = i;
          }
        }
      }
    },
    // 合并行
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        // 合并第一列
        const _row_1 = this.companyArr[rowIndex];
        const _col_1 = _row_1 > 0 ? 1 : 0; // 如果被合并了_row=0则它这个列需要取消
        return {
          rowspan: _row_1,
          colspan: _col_1,
        };
      } else if (columnIndex === 1) {
        // 合并第二列
        const _row_2 = this.simpleArr[rowIndex];
        const _col_2 = _row_2 > 0 ? 1 : 0;
        return {
          rowspan: _row_2,
          colspan: _col_2,
        };
      } else if (columnIndex === 3) {
        // 合并第四列
        const _row_3 = this.symbolArr[rowIndex];
        const _col_3 = _row_3 > 0 ? 1 : 0;
        return {
          rowspan: _row_3,
          colspan: _col_3,
        };
      }
    },
   }
}

补充下:除了第一列和第四列不可编辑,后几列表头不可编辑问题

<template>
<el-table-column
        width="120"
align="center"
        v-for="(column, index) in 6"
        :key="`column-${index}`"
      >
        <template slot="header">
          <div>
            {{ waterForm[`water${index + 1}_label`] }}
          </div>
        </template>
        <template slot-scope="scope">
          <div>
            <el-input
              size="small"
              v-model="waterForm[`water${index + 1}_factor`]"
            ></el-input>
          </div>
        </template>
      </el-table-column>
</template>

data() {
  return {
    ......,
   waterForm: {
        water1_label: "前10分钟",
        water2_label: "前20分钟",
        water3_label: "前30分钟",
        water4_label: "前40分钟",
        water5_label: "前50分钟",
        water6_label: "前60分钟",
      },
  }
}

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏