vue-table实现相同项合并,跨行跨列计算

在这里插入图片描述

1.使用vxeTable

<template>
  <div>
    <vxe-table border resizable:true :scroll-y="{ enabled: false }" :span-method="mergeRowMethod" :data="tableData">
      <vxe-column field="mineralName" title="矿产名称(矿产组合)"></vxe-column>
      <vxe-column field="unitNmae" title="统计对急及资源储量单位"></vxe-column>
      <vxe-column field="brand" title="矿石工业类型及品级(牌号)"></vxe-column>
      <vxe-column field="quality" title="矿石主要成分及质量指标"><template slot-scope="scope">
          <span v-if="scope.row.wbsName == ''">
            <p>自己定义的值</p>
          </span>
          <span v-if="scope.row.wbsName !== ''">
            <p>{{ scope.row.wbsName }}</p>
          </span>
        </template></vxe-column>
      <vxe-colgroup title="截止2022年底查明资源储量及年度变化情况" align="center">
        <vxe-column field="typeEncoding" title="类型编码" align="center"></vxe-column>
        <vxe-column field="earlyTenure" title="年初保有" align="center"></vxe-column>
        <vxe-column field="yearAccumulation" title="年初累计" align="center"></vxe-column>
        <vxe-column field="expNumber" title="开采量" align="center"></vxe-column>
        <vxe-column field="amountOfLoss" title="损失量" align="center"></vxe-column>
        <vxe-column field="survey" title="勘查增减" align="center"></vxe-column>
        <vxe-column field="rollBack" title="重算增减" align="center"></vxe-column>
        <vxe-column field="amountOfOverlay" title="审批压覆量" align="center"></vxe-column>
        <vxe-column field="other" title="其他" align="center"></vxe-column>
        <vxe-column field="yearEndTenure" title="年末保有" align="center"></vxe-column>
        <vxe-column field="cumulative" title="累计查明" align="center"></vxe-column>
      </vxe-colgroup>
    </vxe-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      tableData: [
        {
          mineralName: "铅矿(共生矿产)312321",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化锌矿石、混合锌矿石不分品级",
          quality: "P6 0.",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨11",
          brand: "硫化铅矿石不分品级",
          quality: "P6 0.907 96",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
      ],
      keys: []
    };
  },
  created() {
    this.allProp();
  },
  methods: {
    //获取所有需要合并的属性
    allProp() {
      console.log(this.keys);
    },
    // 通用行合并函数(将相同多列数据合并为一行)
    mergeRowMethod({ row, _rowIndex, column, visibleData }) {
      const fields = ["mineralName", "unitNmae", "brand", "quality"];
      console.log('row, _rowIndex, column, visibleData ',row, _rowIndex, column, visibleData );
      const cellValue = row[column.property];
      for (let j = 0; j < fields.length; j++) {
        if (cellValue && fields[j].includes(column.property)) {
          const prevRow = visibleData[_rowIndex - 1];
          let nextRow = visibleData[_rowIndex + 1];
          if (prevRow && prevRow[column.property] === cellValue) {
            return { rowspan: 0, colspan: 0 };
          } else {
            let countRowspan = 1;
            while (nextRow && nextRow[column.property] === cellValue) {
              nextRow = visibleData[++countRowspan + _rowIndex];
            }
            if (countRowspan > 1) {
              return { rowspan: countRowspan, colspan: 1 };
            }
          }
        }
      }
    }
  }
};
</script>
<style></style>

2.原生实现

<template>
  <div class="hello">
    <table class="table">
      <thead>
        <tr v-for="(items, i) in newArr" :key="i">
          <th
            v-for="(item, j) in items"
            :key="j"
            :rowspan="item.rowspan"
            :colspan="item.colspan"
          >
            {{ item.title }}
          </th>
        </tr>
      </thead>
      <tbody v-if="dataList">
        <tr v-for="(items, index) in dataList" :key="index">
          <td
            v-for="(item, i) in items.tdList"
            :key="i"
            :rowspan="resetRowSpan(index, item)"
          >
            {{ items[item] }}
          </td>
        </tr>
      </tbody>
      <tbody v-else>
        <tr v-for="(items, index) in dataList" :key="index">
          <td v-for="(item, j) in colKeyList" :key="j">{{ items[item] }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {},
  data() {
    return {
      columns: [
        {
          title: "矿产名称(矿产组合)",
          key: "mineralName",
          hasrowspan: true
        },
        {
          title: "统计对急及资源储量单位",
          key: "unitNmae",
          hasrowspan: true
        },
        {
          title: "矿石工业类型及品级(牌号)",
          key: "brand",
          hasrowspan: true
        },
        {
          title: "矿石主要成分及质量指标",
          key: "quality",
          hasrowspan: true
        },
        {
          title: "截止2022年底查明资源储量及年度变化情况",
          children: [
            {
              title: "类型编码",
              key: "typeEncoding",
              align: "center"
            },
            {
              title: "年初保有",
              key: "earlyTenure",
              align: "center"
            },
            {
              title: "年初累计",
              key: "yearAccumulation",
              align: "center"
            },
            {
              title: "开采量",
              key: "expNumber",
              align: "center"
            },
            {
              title: "损失量",
              key: "amountOfLoss",
              align: "center"
            },
            {
              title: "勘查增减",
              key: "survey",
              align: "center"
            },
            {
              title: "重算增减",
              key: "rollBack",
              align: "center"
            },
            {
              title: "审批压覆量",
              key: "amountOfOverlay",
              align: "center"
            },
            {
              title: "其他",
              key: "other",
              align: "center"
            },
            {
              title: "年末保有",
              key: "yearEndTenure",
              align: "center"
            },
            {
              title: "累计查明",
              key: "cumulative",
              align: "center"
            }
          ]
        }
      ], //表头原始参数
      newArr: [[]], //表头
      maxHeight: 1, //表头总共占的行数
      colKeyList: [], //所有的key
      dataList: [
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化铅矿石不分品级",
          quality: "P6 0.907 96",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化铅矿石不分品级",
          quality: "P6 0.907 96",
          typeEncoding: "推断资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化锌矿石、混合锌矿石不分品级",
          quality: "P6 0.",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化铅矿石不分品级",
          quality: "P6 0.907 96",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        },
        {
          mineralName: "铅矿(共生矿产)",
          unitNmae: "铅吨矿石千吨",
          brand: "硫化铅矿石不分品级",
          quality: "P6 0.907 96",
          typeEncoding: "探明资源量",
          yearAccumulation: "2833/245.69",
          earlyTenure: "",
          expNumber: "",
          amountOfLoss: "",
          survey: "",
          rollBack: "",
          amountOfOverlay: "",
          other: "",
          yearEndTenure: "",
          cumulative: ""
        }
      ], //tbody具体数据
      needRowSpan: [], //tbody需要跨行的key
      span: {} //所跨的行数
    };
  },
  mounted() {
    this.maxHeight = this.getMaxFloor(this.columns); //1. 计算出表头一共需要多少行
    this.columnsHandle(this.columns); //2. 对表头进行处理
    this.dataHandle(this.dataList, this.needRowSpan); // 3. 对数据进行处理(传入参数: 具体数据,需要跨行列的(key))
  },
  methods: {
    resetRowSpan(row, key) {
      if (this.span[key] && this.span[key][row]) {
        return this.span[key][row];
      }
      return 1;
    },
    gerMaxCol(items) {
      let max = 0;
      function each(data) {
        if (max < data.length) {
          max = data.length;
        }
        data.forEach((item) => {
          if (item.children) {
            each(item.children);
          }
        });
      }
      each(items);
      return max;
    },
    getMaxFloor(treeData) {
      let max = 0;
      function each(data, floor) {
        data.forEach((e) => {
          if (floor > max) {
            max = floor;
          }
          if (e.children && e.children.length > 0) {
            each(e.children, floor + 1);
          }
        });
      }
      each(treeData, 1);
      return max;
    },
    columnsHandle(treeData) {
      const that = this;
      const maxFloor = this.maxHeight;
      function each(data, index) {
        if (that.newArr[index] === undefined) {
          that.newArr[index] = [];
        }
        data.forEach((e) => {
          const obj = {
            title: e.title,
            key: e.key,
            rowspan: maxFloor,
            colspan: 1
          };
          if (e.children) {
            obj.colspan = that.gerMaxCol(e.children);
            obj.rowspan = maxFloor - that.getMaxFloor(e.children);
          } else {
            that.colKeyList.push(e.key);
            if (e.hasrowspan) {
              //  如果存在hasrowspan属性并且值为true,则表明该key列存在跨行
              that.needRowSpan.push(e.key);
            }
          }
          that.newArr[index].push(obj);
          if (e.children && e.children.length > 0) {
            each(e.children, index + 1);
          }
        });
      }
      each(treeData, 0);
    },
    dataHandle(dataList, needRowSpan) {
      needRowSpan.forEach((key) => {
        const sum = {};
        let i = 0;
        let k = 0;
        const that = this;
        for (let j = 0; j < dataList.length; j += 1) {
          i += 1;
          let tdList = [];
          if (dataList[j].tdList) {
            tdList = [...dataList[j].tdList];
          } else {
            tdList = [...that.colKeyList];
          }
          if (
            dataList[j - 1] &&
            (dataList[j][key] === dataList[j - 1][key] || !dataList[j][key])
          ) {
            const index = tdList.indexOf(key);
            if (index > -1) {
              tdList.splice(index, 1);
            }
          }
          dataList[j].tdList = tdList;
          if (dataList[j + 1] && dataList[j + 1][key]) {
            if (dataList[j][key] !== dataList[j + 1][key]) {
              sum[k] = i;
              i = 0;
              k = j + 1;
            }
          } else if (!dataList[j + 1]) {
            sum[k] = i;
          }
        }
        this.span[key] = sum;
      });
      this.showTable = true;
    }
  }
};
</script>
<style lang="scss" scoped>
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  color: #515a6e;
  border: 1px solid #515a6e;
}
.table thead tr th {
  height: 40px;
  white-space: nowrap;
  overflow: hidden;
  background-color: #f8f8f9;
}
td,
th {
  text-align: center;
  border: 1px solid #e8eaec;
}
.table thead tr th,
.table tbody tr td {
  padding: 0 10px;
}
.table tbody tr td {
  height: 48px;
}
</style>

  • 存在问题:返回的数据需要按相同字符的顺序进行返回,不然合并错乱
  • 如果返回数据是树型数据,也可以扁平化之后再进行处理
  // 扁平化树
    flatTree(list) {
      return list.reduce((ls, item) => {
        let { children, ...res } = item;
        if (children && children.length) {
          return ls.concat(res, this.flatTree(children));
        } else {
          return ls.concat(res);
        }
      }, []);
    },

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值