element-ui的table跨行合并

  • 效果图

a3cc14f0fa2a41cf9b077ac8e53709f7

  • 代码

      <template>
        <el-container class="car-head">
          <el-header height="auto">
              <el-form :inline="true"
                      :model="formObj"
                      @submit.native.prevent
                      label-width="120px"
                      class="demo-form-inline">
                <el-form-item label="关键字:"
                              prop="">
                  <el-input placeholder="请输入"
                            clearable
                            @keyup.enter.native="onSearch"
                            v-model="formObj.keyWord">
                  </el-input>
                </el-form-item>
                <el-form-item label=" ">
                  <el-button @click="onSearch">查询</el-button>
                </el-form-item>
              </el-form>
          </el-header>
          <el-main class="car-box">
            <el-table :data="tableData"
                      border
                      height="100%"
                      v-loading="loading"
                      element-loading-text="努力加载中"
                      element-loading-spinner="el-icon-loading"
                      element-loading-background="rgba(0, 0, 0, 0.8)"
                      highlight-current-row
                      row-key="id"
                      ref="multipleTable"
                      :span-method="handleSpanMethod"
                      :cell-style="{fontSize:'12px',color:'#171a1d'}"
                      :header-cell-style="{background:'#f7f8fa',color:'#171a1d',fontSize:'14px'}"
                      style="width: 100%">
              <el-table-column prop="field_m7ejanne"
                              align="center"
                              label="宿舍所属区域">
              </el-table-column>
              <el-table-column prop="field_lkzlykrr"
                              align="center"
                              label="宿舍名称">
              </el-table-column>
              <el-table-column prop="field_lkzlykrt"
                              align="center"
                              label="宿舍地址">
              </el-table-column>
              <el-table-column prop="field_lkzlykrv"
                              align="center"
                              label="房间号">
              </el-table-column>
              <el-table-column prop="field_lkzlyksb"
                              align="center"
                              label="房间规格">
              </el-table-column>
              <el-table-column prop="field_lkzmzcfc"
                              align="center"
                              label="剩余可住人数">
              </el-table-column>
              <el-table-column prop="field_lkznbefl"
                              align="center"
                              label="姓名">
              </el-table-column>
              <el-table-column prop="field_lkzlyks9"
                              align="center"
                              label="性别">
              </el-table-column>
              <el-table-column prop="field_lkzlyks3"
                              align="center"
                              label="部门">
              </el-table-column>
              <el-table-column prop="field_lkznfbu1"
                              align="center"
                              label="入住时间">
                <template #default="{row,column}">
                  <div>{{ row[column.property]?$moment(row[column.property]).format("YYYY-MM-DD"):"" }}</div>
                </template>
              </el-table-column>
              <el-table-column prop="field_lkznfbtz"
                              align="center"
                              label="搬离时间">
                <template #default="{row,column}">
                  <div>{{ row[column.property]?$moment(row[column.property]).format("YYYY-MM-DD"):"" }}</div>
                </template>
              </el-table-column>
            </el-table>
          </el-main>
          <el-footer height="auto"
                    class="text-center">
            <el-pagination :current-page.sync="form.pageIndex"
                          @size-change="handleSizeChange"
                          @current-change="handleCurrentChange"
                          :page-size="form.pageSize"
                          :page-sizes="[20, 40, 60, 80,100]"
                          layout="total, sizes, prev, pager, next, jumper"
                          :total="form.boskTotal">
            </el-pagination>
          </el-footer>
        </el-container>
      </template>
    
      <script lang="ts">
        import { Component, Vue } from "vue-property-decorator";
    
        @Component({
          name: "",
          components: {
          },
        })
        export default class extends Vue {
          ShowSearch = true;
          form = {
            pageIndex: 1,
            pageSize: 20,
            boskTotal: 0,
          };
          formObj = {
            keyWord: "",
          };
          isSearch = {
            keyWord: "",
          };
          $refs: {
            multipleTable;
          };
          tableData = [
            {
              field_m7ejanne: "诸暨",
              field_lkzlykrr: "cs宿舍",
              field_lkzlykrt: "绍兴市暨阳街道上城y幢",
              field_lkzlykrv: "20403",
              field_lkzlyksb: "2人间",
              field_lkzmzcfc: "2人",
              field_lkznbefl: "张三",
              field_lkzlyks9: "女",
              field_lkzlyks3: "肉肉大米(万风新天地店)",
              field_lkznfbu1: "20251010",
              field_lkznfbtz: "20251121",
            },
            {
              field_m7ejanne: "诸暨",
              field_lkzlykrr: "cs宿舍",
              field_lkzlykrt: "绍兴市暨阳街道上城y幢",
              field_lkzlykrv: "20403",
              field_lkzlyksb: "2人间",
              field_lkzmzcfc: "2人",
              field_lkznbefl: "李四",
              field_lkzlyks9: "女",
              field_lkzlyks3: "肉肉大米(万风新天地店)",
              field_lkznfbu1: "20251010",
              field_lkznfbtz: null,
            },
            {
              field_m7ejanne: "诸暨",
              field_lkzlykrr: "测试宿舍",
              field_lkzlykrt: "绍兴市暨阳街道上城x幢",
              field_lkzlykrv: "11304",
              field_lkzlyksb: "3人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "王五",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(万风新天地店)",
              field_lkznfbu1: "20251010",
              field_lkznfbtz: null,
            },
            {
              field_m7ejanne: "诸暨",
              field_lkzlykrr: "测试宿舍",
              field_lkzlykrt: "绍兴市暨阳街道上城x幢",
              field_lkzlykrv: "11304",
              field_lkzlyksb: "3人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "雷六",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(万风新天地店)",
              field_lkznfbu1: "20251010",
              field_lkznfbtz: null,
            },
            {
              field_m7ejanne: "诸暨",
              field_lkzlykrr: "测试宿舍",
              field_lkzlykrt: "绍兴市暨阳街道上城x幢",
              field_lkzlykrv: "11304",
              field_lkzlyksb: "3人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "马七",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(万风新天地店)",
              field_lkznfbu1: "20251010",
              field_lkznfbtz: null,
            },
    
            {
              field_m7ejanne: "东莞",
              field_lkzlykrr: "哈哈哈宿舍",
              field_lkzlykrt: "东莞市东城区xx期",
              field_lkzlykrv: "B1215",
              field_lkzlyksb: "4人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "杨八",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(松山湖万象汇店)",
              field_lkznfbu1: "20240925",
              field_lkznfbtz: "20241227",
            },
            {
              field_m7ejanne: "东莞",
              field_lkzlykrr: "哈哈哈宿舍",
              field_lkzlykrt: "东莞市东城区xx期",
              field_lkzlykrv: "B1215",
              field_lkzlyksb: "4人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "测试",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(松山湖万象汇店)",
              field_lkznfbu1: "20240925",
              field_lkznfbtz: "20241126",
            },
            {
              field_m7ejanne: "东莞",
              field_lkzlykrr: "哈哈哈宿舍",
              field_lkzlykrt: "东莞市东城区xx期",
              field_lkzlykrv: "B1215",
              field_lkzlyksb: "4人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "随机",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(民盈国贸城店)",
              field_lkznfbu1: "20240928",
              field_lkznfbtz: "20250630",
            },
            {
              field_m7ejanne: "东莞",
              field_lkzlykrr: "哈哈哈宿舍",
              field_lkzlykrt: "东莞市东城区xx期",
              field_lkzlykrv: "B1215",
              field_lkzlyksb: "4人间",
              field_lkzmzcfc: "1人",
              field_lkznbefl: "名称",
              field_lkzlyks9: "男",
              field_lkzlyks3: "肉肉大米(民盈国贸城店)",
              field_lkznfbu1: "20250702",
              field_lkznfbtz: null,
            },
    
            {
              field_m7ejanne: "台州",
              field_lkzlykrr: "嘿嘿宿舍",
              field_lkzlykrt: "浙江省台州市xx",
              field_lkzlykrv: "415",
              field_lkzlyksb: "1人间",
              field_lkzmzcfc: "0人",
              field_lkznbefl: "哈哈",
              field_lkzlyks9: "女",
              field_lkzlyks3: "肉肉大米(中盛城市广场店)",
              field_lkznfbu1: "20251008",
              field_lkznfbtz: null,
            },
          ]; // 表格数据
          loading = false;
          spanArr = []; // 存储每一行的合并规则
          position = 0; // 辅助计算合并位置的临时变量
          spanList = []; // 存储每一行的合并规则
          tmpIndex = 0; // 辅助计算合并位置的临时变量
          created() {
            // this.InitLoad();
          }
          mounted() {
            this.calculateSpan();
            this.calculateSpan1();
          }
    
          // 预计算合并规则
          calculateSpan() {
            this.spanArr = []; // 重置合并规则
            this.position = 0; // 重置位置指针
    
            if (this.tableData.length === 0) {
              return;
            }
    
            // 从第一行开始遍历
            this.spanArr.push(1); // 第一行默认合并行数为1
    
            for (let i = 1; i < this.tableData.length; i++) {
              // 获取当前行和上一行的关键标识(用于判断是否需要合并)
              const currentKey = this.getRowKey(this.tableData[i]);
              const prevKey = this.getRowKey(this.tableData[i - 1]);
    
              if (currentKey === prevKey) {
                // 若当前行与上一行标识相同,合并行数+1,当前行合并行数设为0(隐藏)
                this.spanArr[this.position] += 1;
                this.spanArr.push(0);
              } else {
                // 若不同,重置位置指针,当前行合并行数设为1
                this.position = i;
                this.spanArr.push(1);
              }
            }
            // console.log(this.spanArr);
          }
    
          calculateSpan1() {
            this.spanList = []; // 重置合并规则
            this.tmpIndex = 0; // 重置位置指针
    
            if (this.tableData.length === 0) {
              return;
            }
    
            // 从第一行开始遍历
            this.spanList.push(1); // 第一行默认合并行数为1
    
            for (let i = 1; i < this.tableData.length; i++) {
              // 获取当前行和上一行的关键标识(用于判断是否需要合并)
              const currentKey = this.getRowKey1(this.tableData[i]);
              const prevKey = this.getRowKey1(this.tableData[i - 1]);
    
              if (currentKey === prevKey) {
                // 若当前行与上一行标识相同,合并行数+1,当前行合并行数设为0(隐藏)
                this.spanList[this.tmpIndex] += 1;
                this.spanList.push(0);
              } else {
                // 若不同,重置位置指针,当前行合并行数设为1
                this.tmpIndex = i;
                this.spanList.push(1);
              }
            }
            console.log(this.spanList);
          }
    
          // 生成行的唯一标识(合并的判断依据)
          getRowKey(row) {
            // 合并的核心字段:宿舍所属区域+宿舍名称+宿舍地址+房间号+房间规格+剩余可住人数
            return [
              row.field_m7ejanne, // 宿舍所属区域
              row.field_lkzlykrr, // 宿舍名称
              // row.field_lkzlykrt, // 宿舍地址
              // row.field_lkzlykrv, // 房间号
              // row.field_lkzlyksb, // 房间规格
              // row.field_lkzmzcfc, // 剩余可住人数
            ].join("|"); // 用特殊符号拼接,避免字段值本身包含分隔符导致误判
          }
          getRowKey1(row) {
            // 合并的核心字段:宿舍地址+房间号+房间规格+剩余可住人数
            return [
              row.field_lkzlykrt, // 宿舍地址
              row.field_lkzlykrv, // 房间号
              row.field_lkzlyksb, // 房间规格
              row.field_lkzmzcfc, // 剩余可住人数
            ].join("|"); // 用特殊符号拼接,避免字段值本身包含分隔符导致误判
          }
    
          // 表格合并方法(核心)
          handleSpanMethod({ row, column, rowIndex, columnIndex }) {
            // 只处理前6列(索引0-5),其他列不合并
            if (columnIndex < 6) {
              if (columnIndex < 2) {
                const rowspan = this.spanArr[rowIndex];
                const colspan = rowspan > 0 ? 1 : 0; // 合并行时列占比为1,0则隐藏
                return { rowspan, colspan };
              } else if (columnIndex > 1 && columnIndex < 6) {
                const rowspan = this.spanList[rowIndex];
                const colspan = rowspan > 0 ? 1 : 0; // 合并行时列占比为1,0则隐藏
                return { rowspan, colspan };
              }
            }
            // 不需要合并的列返回默认值(不合并)
            return { rowspan: 1, colspan: 1 };
          }
    
          /** 初始化数据 */
          InitLoad() {
          
          }
    
          /** 搜索 */
          onSearch() {
            this.isSearch = this.formObj;
            this.form.pageIndex = 1;
    
            this.InitLoad();
          }
    
          handleSizeChange(val) {
            this.form.pageSize = val;
            this.InitLoad();
          }
          handleCurrentChange(val) {
            this.form.pageIndex = val;
            this.InitLoad();
          }
        }
      </script>
    
      <style lang="scss" scoped>
        .car-head {
          background: #fff;
          width: 100%;
          height: 100%;
          .car-box {
            background: #fff;
          }
    
        }
    
      </style>
    
  • 每列是个单独计算合并方法

    <template>
      <el-container class="car-head">
        <el-header height="auto">
            <el-form :inline="true"
                    :model="formObj"
                    @submit.native.prevent
                    label-width="120px"
                    class="demo-form-inline">
              <el-form-item label="关键字:"
                            prop="">
                <el-input placeholder="请输入"
                          clearable
                          @keyup.enter.native="onSearch"
                          v-model="formObj.keyWord">
                </el-input>
              </el-form-item>
              <el-form-item label=" ">
                <el-button @click="onSearch">查询</el-button>
              </el-form-item>
            </el-form>
        </el-header>
        <el-main class="car-box">
          <el-table :data="tableData"
                    border
                    height="100%"
                    v-loading="loading"
                    element-loading-text="努力加载中"
                    element-loading-spinner="el-icon-loading"
                    element-loading-background="rgba(0, 0, 0, 0.8)"
                    highlight-current-row
                    row-key="id"
                    ref="multipleTable"
                    :span-method="handleSpanMethod"
                    :cell-style="{fontSize:'12px',color:'#171a1d'}"
                    :header-cell-style="{background:'#f7f8fa',color:'#171a1d',fontSize:'14px'}"
                    style="width: 100%">
            <!-- 前6列 - 每列独立合并规则 -->
            <el-table-column prop="field_m7ejanne"
                            align="center"
                            label="宿舍所属区域"></el-table-column>
            <el-table-column prop="field_lkzlykrr"
                            align="center"
                            label="宿舍名称"></el-table-column>
            <el-table-column prop="field_lkzlykrt"
                            align="center"
                            label="宿舍地址"></el-table-column>
            <el-table-column prop="field_lkzlykrv"
                            align="center"
                            label="房间号"></el-table-column>
            <el-table-column prop="field_lkzlyksb"
                            align="center"
                            label="房间规格"></el-table-column>
            <el-table-column prop="field_lkzmzcfc"
                            align="center"
                            label="剩余可住人数"></el-table-column>
            <!-- 其他列 -->
            <el-table-column prop="field_lkznbefl"
                            align="center"
                            label="姓名"></el-table-column>
            <el-table-column prop="field_lkzlyks9"
                            align="center"
                            label="性别"></el-table-column>
            <el-table-column prop="field_lkzlyks3"
                            align="center"
                            label="部门"></el-table-column>
            <el-table-column prop="field_lkznfbu1"
                            align="center"
                            label="入住时间">
              <template #default="{row,column}">
                <div>{{ row[column.property]?$moment(row[column.property]).format("YYYY-MM-DD"):"" }}</div>
              </template>
            </el-table-column>
            <el-table-column prop="field_lkznfbtz"
                            align="center"
                            label="搬离时间">
              <template #default="{row,column}">
                <div>{{ row[column.property]?$moment(row[column.property]).format("YYYY-MM-DD"):"" }}</div>
              </template>
            </el-table-column>
          </el-table>
        </el-main>
        <el-footer height="auto"
                  class="text-center">
          <el-pagination :current-page.sync="form.pageIndex"
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                        :page-size="form.pageSize"
                        :page-sizes="[20, 40, 60, 80,100]"
                        layout="total, sizes, prev, pager, next, jumper"
                        :total="form.boskTotal">
          </el-pagination>
        </el-footer>
      </el-container>
    </template>
    
    <script lang="ts">
      import { Component, Vue } from "vue-property-decorator";
      import { getCheckInList } from "@/api/report/checkInList";
    
      @Component({
        name: "CheckInList",
        components: {  },
      })
      export default class extends Vue {
        ShowSearch = true;
        form = {
          pageIndex: 1,
          pageSize: 20,
          boskTotal: 0,
        };
        formObj = { keyWord: "" };
        isSearch = { keyWord: "" };
        $refs: { multipleTable: any };
    
        tableData = [
          {
            field_m7ejanne: "诸暨",
            field_lkzlykrr: "cs宿舍",
            field_lkzlykrt: "绍兴市暨阳街道上城y幢",
            field_lkzlykrv: "20403",
            field_lkzlyksb: "2人间",
            field_lkzmzcfc: "2人",
            field_lkznbefl: "张三",
            field_lkzlyks9: "女",
            field_lkzlyks3: "肉肉大米(万风新天地店)",
            field_lkznfbu1: "20251010",
            field_lkznfbtz: "20251121",
          },
          {
            field_m7ejanne: "诸暨",
            field_lkzlykrr: "cs宿舍",
            field_lkzlykrt: "绍兴市暨阳街道上城y幢",
            field_lkzlykrv: "20403",
            field_lkzlyksb: "2人间",
            field_lkzmzcfc: "2人",
            field_lkznbefl: "李四",
            field_lkzlyks9: "女",
            field_lkzlyks3: "肉肉大米(万风新天地店)",
            field_lkznfbu1: "20251010",
            field_lkznfbtz: null,
          },
          {
            field_m7ejanne: "诸暨",
            field_lkzlykrr: "测试宿舍",
            field_lkzlykrt: "绍兴市暨阳街道上城x幢",
            field_lkzlykrv: "11304",
            field_lkzlyksb: "3人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "王五",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(万风新天地店)",
            field_lkznfbu1: "20251010",
            field_lkznfbtz: null,
          },
          {
            field_m7ejanne: "诸暨",
            field_lkzlykrr: "测试宿舍",
            field_lkzlykrt: "绍兴市暨阳街道上城x幢",
            field_lkzlykrv: "11304",
            field_lkzlyksb: "3人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "雷六",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(万风新天地店)",
            field_lkznfbu1: "20251010",
            field_lkznfbtz: null,
          },
          {
            field_m7ejanne: "诸暨",
            field_lkzlykrr: "测试宿舍",
            field_lkzlykrt: "绍兴市暨阳街道上城x幢",
            field_lkzlykrv: "11304",
            field_lkzlyksb: "1人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "马七",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(万风新天地店)",
            field_lkznfbu1: "20251010",
            field_lkznfbtz: null,
          },
          {
            field_m7ejanne: "东莞",
            field_lkzlykrr: "哈哈哈宿舍",
            field_lkzlykrt: "东莞市东城区xx期",
            field_lkzlykrv: "B1215",
            field_lkzlyksb: "4人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "杨八",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(松山湖万象汇店)",
            field_lkznfbu1: "20240925",
            field_lkznfbtz: "20241227",
          },
          {
            field_m7ejanne: "东莞",
            field_lkzlykrr: "哈哈哈宿舍",
            field_lkzlykrt: "东莞市东城区xx期",
            field_lkzlykrv: "B1215",
            field_lkzlyksb: "4人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "测试",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(松山湖万象汇店)",
            field_lkznfbu1: "20240925",
            field_lkznfbtz: "20241126",
          },
          {
            field_m7ejanne: "东莞",
            field_lkzlykrr: "哈哈哈宿舍",
            field_lkzlykrt: "东莞市东城区xx期",
            field_lkzlykrv: "B1215",
            field_lkzlyksb: "4人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "随机",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(民盈国贸城店)",
            field_lkznfbu1: "20240928",
            field_lkznfbtz: "20250630",
          },
          {
            field_m7ejanne: "东莞",
            field_lkzlykrr: "哈哈哈宿舍",
            field_lkzlykrt: "东莞市东城区xx期",
            field_lkzlykrv: "B1215",
            field_lkzlyksb: "4人间",
            field_lkzmzcfc: "1人",
            field_lkznbefl: "名称",
            field_lkzlyks9: "男",
            field_lkzlyks3: "肉肉大米(民盈国贸城店)",
            field_lkznfbu1: "20250702",
            field_lkznfbtz: null,
          },
          {
            field_m7ejanne: "台州",
            field_lkzlykrr: "嘿嘿宿舍",
            field_lkzlykrt: "浙江省台州市xx",
            field_lkzlykrv: "415",
            field_lkzlyksb: "1人间",
            field_lkzmzcfc: "0人",
            field_lkznbefl: "哈哈",
            field_lkzlyks9: "女",
            field_lkzlyks3: "肉肉大米(中盛城市广场店)",
            field_lkznfbu1: "20251008",
            field_lkznfbtz: null,
          },
        ];
    
        loading = false;
        columnSpanRules = {
          0: [], // 宿舍所属区域
          1: [], // 宿舍名称
          2: [], // 宿舍地址
          3: [], // 房间号
          4: [], // 房间规格
          5: [], // 剩余可住人数
        };
    
        created() {}
    
        mounted() {
          // 初始化计算所有列的合并规则
          this.calculateAllColumnSpanRules();
        }
    
        /**
        * 计算所有列的合并规则(每列独立计算)
        */
        calculateAllColumnSpanRules() {
          const data = this.tableData;
          if (!data.length) {
            return;
          }
    
          // 1. 计算【宿舍所属区域】列合并规则(仅按区域字段判断)
          this.columnSpanRules[0] = this.calculateSingleColumnSpan(
            data,
            row => row.field_m7ejanne // 仅判断区域字段
          );
    
          // 2. 计算【宿舍名称】列合并规则(按区域+宿舍名称判断)
          this.columnSpanRules[1] = this.calculateSingleColumnSpan(
            data,
            row => `${row.field_m7ejanne}|${row.field_lkzlykrr}` // 区域+宿舍名称
          );
    
          // 3. 计算【宿舍地址】列合并规则(按区域+宿舍名称+地址判断)
          this.columnSpanRules[2] = this.calculateSingleColumnSpan(
            data,
            row => `${row.field_m7ejanne}|${row.field_lkzlykrr}|${row.field_lkzlykrt}` // 区域+宿舍名称+地址
          );
    
          // 4. 计算【房间号】列合并规则(按区域+宿舍名称+地址+房间号判断)
          this.columnSpanRules[3] = this.calculateSingleColumnSpan(
            data,
            row =>
              `${row.field_m7ejanne}|${row.field_lkzlykrr}|${row.field_lkzlykrt}|${row.field_lkzlykrv}` // 区域+宿舍名称+地址+房间号
          );
    
          // 5. 计算【房间规格】列合并规则(按区域+宿舍名称+地址+房间号+规格判断)
          this.columnSpanRules[4] = this.calculateSingleColumnSpan(
            data,
            row =>
              `${row.field_m7ejanne}|${row.field_lkzlykrr}|${row.field_lkzlykrt}|${row.field_lkzlykrv}|${row.field_lkzlyksb}` // 区域+宿舍名称+地址+房间号+规格
          );
    
          // 6. 计算【剩余可住人数】列合并规则(按区域+宿舍名称+地址+房间号+规格+剩余人数判断)
          this.columnSpanRules[5] = this.calculateSingleColumnSpan(
            data,
            row =>
              `${row.field_m7ejanne}|${row.field_lkzlykrr}|${row.field_lkzlykrt}|${row.field_lkzlykrv}|${row.field_lkzlyksb}|${row.field_lkzmzcfc}` // 完整房间信息
          );
        }
    
        /**
        * 计算单个列的合并规则(通用方法)
        * @param data 表格数据
        * @param getKeyFunc 生成每行唯一标识的函数
        * @returns 该列的合并规则数组
        */
        calculateSingleColumnSpan(
          data: any[],
          getKeyFunc: (row: any) => string
        ): number[] {
          const spanArr: number[] = [];
          if (!data.length) {
            return spanArr;
          }
    
          let count = 1;
          spanArr.push(1); // 第一行默认合并数为1
    
          for (let i = 1; i < data.length; i++) {
            const currentKey = getKeyFunc(data[i]);
            const prevKey = getKeyFunc(data[i - 1]);
    
            if (currentKey === prevKey) {
              // 当前行与上一行相同,合并数+1,当前行设为0(隐藏)
              count++;
              spanArr.push(0);
            } else {
              // 当前行与上一行不同,记录合并数,重置计数器
              spanArr[spanArr.length - count] = count;
              count = 1;
              spanArr.push(1);
            }
          }
    
          // 处理最后一组数据的合并数
          if (count > 1) {
            spanArr[spanArr.length - count] = count;
          }
    
          return spanArr;
        }
    
        /**
        * 表格合并方法 - 每列独立处理
        */
        handleSpanMethod({
          rowIndex,
          columnIndex,
        }: {
          rowIndex: number;
          columnIndex: number;
        }) {
          // 只处理前6列的合并
          if (columnIndex >= 0 && columnIndex <= 5) {
            const rowspan = this.columnSpanRules[columnIndex][rowIndex];
            const colspan = rowspan > 0 ? 1 : 0;
            return { rowspan, colspan };
          }
    
          // 其他列不合并
          return { rowspan: 1, colspan: 1 };
        }
    
        /**
        * 自定义每列的合并规则(扩展方法)
        * 可单独修改某一列的合并逻辑
        * @param columnIndex 列索引
        * @param getKeyFunc 新的标识生成函数
        */
        updateSingleColumnSpanRule(
          columnIndex: number,
          getKeyFunc: (row: any) => string
        ) {
          this.columnSpanRules[columnIndex] = this.calculateSingleColumnSpan(
            this.tableData,
            getKeyFunc
          );
          // 强制表格重新渲染
          this.$refs.multipleTable?.doLayout();
        }
    
        /** 初始化数据 */
        InitLoad() {
          
        }
    
        /** 搜索 */
        onSearch() {
          this.isSearch = { ...this.formObj }; // 深拷贝避免引用问题
          this.form.pageIndex = 1;
          this.InitLoad();
        }
    
        handleSizeChange(val: number) {
          this.form.pageSize = val;
          this.InitLoad();
        }
    
        handleCurrentChange(val: number) {
          this.form.pageIndex = val;
          this.InitLoad();
        }
      }
    </script>
    
    <style lang="scss" scoped>
      .car-head {
        background: #fff;
        width: 100%;
        height: 100vh;
        display: flex;
        flex-direction: column;
    
        .car-box {
          background: #fff;
          flex: 1;
          padding: 10px;
          overflow: hidden;
        }
    
        .el-header {
          padding: 10px 20px;
          border-bottom: 1px solid #ebeef5;
        }
    
        .el-footer {
          padding: 10px 0;
          border-top: 1px solid #ebeef5;
        }
      }
    
      // 表格样式优化
      :deep(.el-table) {
        td,
        th {
          border-right: 1px solid #ebeef5;
        }
    
        .cell {
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
    
        // 超长地址换行处理
        .cell.el-tooltip {
          white-space: normal;
          line-height: 1.4;
        }
      }
    </style>
    
posted @ 2025-12-04 17:19  不完美的完美  阅读(1)  评论(0)    收藏  举报