image.png

<template>
  <div class="zz-dynamic-table">
    <table class="customTable" border cellpadding="0" cellspacing="0">
      <thead>
        <tr v-for="(aitem, i) in newTheadData" :key="'a' + i">
          <th
            :width="bitem.width ? bitem.width : 'auto'"
            :style="{ width: bitem.width ? bitem.width : 'auto', 'text-align': bitem.align ? bitem.align : 'center' }"
            v-for="(bitem, j) in aitem"
            :key="'b' + j"
            :rowspan="bitem.rowspan"
            :colspan="bitem.colspan"
            v-html="bitem.label"
          ></th>
        </tr>
      </thead>
      <tr v-for="(item, index) in tableData" :key="index">
        <td
          v-for="(item1, key, index1) in item"
          :key="index1"
          :align="thArr[index1].align && key === thArr[index1].key ? thArr[index1].align : 'center'"
        >
          {{ item1 }}
        </td>
      </tr>
    </table>
  </div>
</template>
<script>
export default {
  name: 'zz-dynamic-table',
  props: {
    theadData: {
      type: Array,
      default: () => [
        { key: 'date', label: '日期', align: 'left' },
        {
          label: '配送信息',
          children: [
            { key: 'name', label: '姓名' },
            {
              label: '地址',
              children: [
                { key: 'province', label: '省份' },
                { key: 'city', label: '市区' },
                { key: 'address', label: '详细<br/>地址' }
              ]
            }
          ]
        },
        { key: 'zip', label: '编码' }
      ]
    }
  },
  data() {
    return {
      thArr: [],
      rows: 1,
      tableData: [
        {
          date: '323232',
          name: 'wang',
          province: 'province',
          city: 'city',
          address: 'address',
          zip: 333
        },
        {
          date: '32323221',
          name: 'wang1',
          province: 'province1',
          city: 'city11',
          address: 'address1',
          zip: 555
        }
      ],
      newTheadData: []
    }
  },
  created() {
    this.newTheadData = this.getTheadData(this.theadData)
    // console.log('newTheadData=', this.newTheadData, this.rows)
    this.thArr = this.treeToFlat(this.theadData, [])
    console.log('thArr=', this.thArr)
  },
  methods: {
    treeToFlat(arr, res) {
      let result = res
      arr.forEach(item => {
        if (item.children?.length) {
          this.treeToFlat(item.children, result)
        } else {
          result.push(item)
        }
      })
      return result
    },
    //获取最终结果返出去
    getTableData() {
      this.$nextTick(() => {
        let result = ''
        if (this.tableData && this.tableData.length) {
          result = JSON.stringify(this.tableData)
        }
        this.$emit('input', result)
      })
    },
    addRow() {
      this.tableData.push({})
    },
    //数组中是否有children字段
    isHaveChildren(arr) {
      if (!arr) {
        return false
      }
      for (let i = 0; i < arr.length; i++) {
        let item = arr[i]
        if (item.children && item.children.length) {
          return true
        }
      }
      return false
    },
    //获取该列合并的总数
    getColCount(data) {
      let sum = 0
      if (!data) {
        return sum
      }
      if (!data.children) {
        return sum
      }
      let _this = this
      let fn = function(arr) {
        if (!arr) {
          return sum
        }
        arr.forEach(item => {
          if (item.children) {
            fn(item.children)
          } else {
            sum++
          }
        })
      }
      fn(data.children)
      return sum
    },
    //重组thead数据
    getTheadData(p) {
      let params = JSON.parse(JSON.stringify(p))
      if (!params) {
        return []
      }
      let data = [],
        _this = this
      var fn = function(arr) {
        if (!arr) {
          return []
        }
        // 是否拥有多级表头
        let rowData = []
        if (_this.isHaveChildren(arr)) {
          arr.forEach(item => {
            if (item.children) {
              item.rowspan = 1
              item.colspan = _this.getColCount(item)
              fn(item.children)
            } else {
              item.rowspan = arr.length
              item.colspan = 1
            }
            rowData.push(item)
          })
        } else {
          arr.forEach(item => {
            item.rowspan = 1
            item.colspan = 1
            rowData.push(item)
          })
        }
        data.unshift(rowData)
      }
      if (this.isHaveChildren(params)) {
        //重组
        this.rows = params.length
        fn(params)
      } else {
        //不重组
        data.push(params)
      }
      return data
    }
  },
  watch: {
    theadData(value) {
      this.newTheadData = this.getTheadData(value)
    }
  }
}
</script>
<style lang="less" scoped>
.zz-dynamic-table {
  width: 100%;
}
table {
  width: 100%;
  border-color: #777;
  // border-color: red;
}
thead {
  background: #eee;
}
tr {
  width: 100%;
}
th {
  padding: 3px 2px;
  min-width: 10%;
}
td {
  padding: 3px 2px;
}
</style>

云胡不喜
73 声望11 粉丝

前端的忠实粉丝