数据:

export default [
  {
    id: '5829341',
    projectName: '资本化支出',
    remark: '1',
    childNode: [
      {
        id: '5829342',
        parentId: '5829341',
        projectName: '设备购置',
        money: 660000.00,
        remark: '固定资产'
      },
      {
        id: '5829343',
        parentId: '5829341',
        projectName: '软件购置',
        money: 660000.00,
        remark: '无形资产'
      }
    ]
  },
  {
    id: '5829344',
    projectName: '费用化支出',
    remark: '费用化支出',
    childNode: [
      {
        id: '5829345',
        parentId: '5829344',
        projectName: '材料费',
        remark: '物料消耗、低值易耗品摊销、办公用品'
      },
      {
        id: '5829346',
        parentId: '5829344',
        projectName: '燃料动力费',
        remark: '燃料,外购燃料,燃料油,汽油,柴油,其他燃料油,燃料气,天然气,外购动力等费用,其他,电(一般不予填写)'
      },
      {
        id: '5829371',
        parentId: '5829344',
        projectName: '人员费',
        remark: '员工费用,工资,福利等费用,不超过35%,误餐补贴'
      },
      {
        id: '5829372',
        parentId: '5829344',
        projectName: '管理费',
        remark: '上级管理费,不超过5%'
      },
      {
        id: '5829373',
        parentId: '5829344',
        projectName: '结转',
        remark: '月末结转'
      },
      {
        id: '5829347',
        parentId: '5829344',
        projectName: '其他直接费',
        childNode: [
          {
            id: '5829361',
            parentId: '5829347',
            projectName: '技术服务费',
            remark: '技术服务费,外协费,其他,'
          },
          {
            id: '5829362',
            parentId: '5829347',
            projectName: '办公费',
            remark: '办公费,印刷费,通讯费,电话费,其他通讯费用,发票费用,邮电费,路桥、停车费,其他办公费用,团体会费(不包含办公用品)'
          },
          {
            id: '5829363',
            parentId: '5829347',
            projectName: '差旅费',
            remark: '差旅费,外埠差旅费,市内交通费,市内住宿费,飞机票,住宿补贴,其他,考察联络费(参加会议发生在各项支出)'
          },
          {
            id: '5829364',
            parentId: '5829347',
            projectName: '会议费',
            remark: '会议费,内部会议费,外部会议费(主办会议发生的各项支出)'
          },
          {
            id: '5829365',
            parentId: '5829347',
            projectName: '国际合作与交流费',
            remark: '外宾招待费,出国人员经费'
          },
          {
            id: '5829366',
            parentId: '5829347',
            projectName: '业务招待费',
            remark: '业务招待费'
          },
          {
            id: '5829367',
            parentId: '5829347',
            projectName: '劳务费',
            remark: '劳务费,有偿解除劳动合同人员返聘劳务费,其他劳务费(不予填写)'
          },
          {
            id: '5829368',
            parentId: '5829347',
            projectName: '科研机构',
            remark: ' '
          },
          {
            id: '5829369',
            parentId: '5829347',
            projectName: '其他费用',
            remark: '团体会费'
          },
          {
            id: '5829370',
            parentId: '5829347',
            projectName: '预算外费用',
            remark: '预算外费用,折旧折耗摊销,固定资产折旧,投资性房地产折旧,无形资产摊销等(不予填写)'
          },
          {
            id: '5829348',
            parentId: '5829347',
            projectName: '条件配套费',
            childNode: [
              {
                id: '5829349',
                parentId: '5829348',
                projectName: '租赁费',
                remark: '租赁费,土地租赁费,房屋租赁费,油槽车租赁费,通信线路租赁费等租赁费用'
              },
              {
                id: '5829350',
                parentId: '5829348',
                projectName: '维护及修理费',
                remark: '维护及修理费,房屋建筑物修理费,热力设施维修费,车辆修理费,信息系统维护费等,道路维修费'
              },
              {
                id: '5829351',
                parentId: '5829348',
                projectName: '取暖费',
                remark: '取暖费,不超过2.5%'
              },
              {
                id: '5829352',
                parentId: '5829348',
                projectName: '物业管理费',
                remark: '物业管理费,绿化及环境卫生费,警卫消防费,不超过7.5%'
              },
              {
                id: '5829353',
                parentId: '5829348',
                projectName: '运输费',
                remark: '运输费,一次运费,铁路运费,公路运费,海上运费,管道运费等运输费用'
              }
            ]
          },
          {
            id: '5829354',
            parentId: '5829347',
            projectName: '技术配套费',
            childNode: [
              {
                id: '5829355',
                parentId: '5829354',
                projectName: '测试化验加工',
                remark: '外部加工费,检测费,试验检验费,测试化验加工,试验检验费'
              },
              {
                id: '5829356',
                parentId: '5829354',
                projectName: '设计制图费',
                remark: '设计制图费'
              },
              {
                id: '5829357',
                parentId: '5829354',
                projectName: '资料解释费',
                remark: '资料解释费'
              },
              {
                id: '5829358',
                parentId: '5829354',
                projectName: '出版/文献/信息传播/知识产权事务费',
                remark: '图书资料费,出版/文献/信息传播/知识产权事务费'
              },
              {
                id: '5829359',
                parentId: '5829354',
                projectName: '培训费',
                remark: '其他费用,培训费,国家项目劳务费,研究生经费,国际合作交流费,其他'
              },
              {
                id: '5829360',
                parentId: '5829354',
                projectName: '咨询评审费',
                remark: '咨询审计费,审计费,评估费,法律费用,市场调查费,咨询费,其他'
              }
            ]
          }
        ]
      }
    ]
  }
]
View Code
 html
<el-table
            ref="table"
            :data="tableList"
            :show-header="true"
            border
            size="mini"
            :span-method="arraySpanMethod"
            show-summary
            :summary-method="getSummaries"
            :header-cell-style="hideHeader"
          >
            <el-table-column
              prop="index"
              label="序号"
              width="60"
              header-align="center"
              align="center"
            >
              <template slot-scope="scope">{{ scope.row.repertory }}</template>
            </el-table-column>
            <el-table-column label="项目分类" header-align="center">
              <el-table-column v-for="item in titleKey" :key="item" :prop="item" label />
            </el-table-column>

            <el-table-column
              prop="expense"
              label="预算经费(单位:元)"
              width="180"
              header-align="center"
              align="right"
            >
              <template slot-scope="scope">
                <el-input-number
                  v-model="scope.row.expense"
                  :min="0"
                  :step="1"
                  style="width:100%"
                  :controls="false"
                  :disabled="!receiveInfo"
                  placeholder="请输入费用化预算(万元"
                  size="mini"
                />
              </template>
            </el-table-column>
            <el-table-column prop="remark" label="备注" header-align="center" show-overflow-tooltip />
          </el-table>
View Code

data定义的数据

data() {
    return {
      resultList: [],
      nameMap: {},
      titleKey: [],
      backUpItem: Object.create(null),
      treeList,
      treeMap: {},
      tableList: [],
      matrixMap: {}
    }
  },

事件

created() {
    console.log(this.treeList)
    this.initData(this.treeList)
    const tableList = this.initTableList()
    for (let i = 0; i < tableList.length; i++) {
      for (let j = 0; j < this.titleKey.length + 3; j++) {
        if (j === 0) {
          if (this.nameMap[tableList[i]['index']]) {
            this.matrixMap[`${i}${j}`] = [
              this.nameMap[tableList[i]['index']].row - 1,
              1
            ]
          } else {
            this.matrixMap[`${i}${j}`] = [0, 0]
          }
        } else if (j > 0 && j <= this.titleKey.length) {
          if (tableList[i][`key${j}`]) {
            this.matrixMap[`${i}${j}`] = [
              this.nameMap[tableList[i][`key${j}`]].row > 1
                ? this.nameMap[tableList[i][`key${j}`]].row - 1
                : this.nameMap[tableList[i][`key${j}`]].row,
              this.nameMap[tableList[i][`key${j}`]].col
            ]
          } else {
            this.matrixMap[`${i}${j}`] = [0, 0]
          }
        } else {
          this.matrixMap[`${i}${j}`] = [1, 1]
        }
      }
    }
    this.tableList = tableList
  },
  methods: {
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      return this.matrixMap[`${rowIndex}${columnIndex}`]
    },
    handleSetCol(item, rank) {
      // 设置父元素跨了多少行 递归设置 因为所有的父元素跨的行都相应的增加
      item.row = item.row + 1
      // 这里需要递归进行设置祖先元素
      this.handleSetRow(item.rank, rank + 1 - item.rank)
      if (this.treeMap[item.parentId]) {
        this.handleSetCol(this.treeMap[item.parentId], rank)
      }
    },
    handleSetRow(rank, col) {
      // 设置所有对应的rank层级的元素垮了多少列
      Object.values(this.treeMap).forEach(item => {
        if (item.rank === rank && !item.childNode && item.rank != 1) {
          item.col = col
        }
      })
    },
    initData(list, step) {
      // 递归保证下面层序遍历生成的数组还是有序的
      const sortList = list => {
        list.forEach(item => {
          if (Array.isArray(item.childNode)) {
            sortList(item.childNode)
          } else {
            this.resultList.push(this.treeMap[item.id])
          }
        })
      }
      // 层序遍历
      // 当前层级便利的队列
      let queue = [...this.treeList]
      // 下一个层级要遍历的队列
      let nextQueue = []
      let rank = 0
      while (queue.length) {
        const len = queue.length
        for (let i = 0; i < len; i++) {
          const item = queue[i]
          item.rank = rank + 1
          if (!item.col) {
            item.row = 1
            item.col = 1
          }
          // id  =》 item
          // name => item
          this.treeMap[item.id] = item
          this.nameMap[item.projectName] = item
          // 找到度为0的孩子节点
          if (this.treeMap[item.parentId] && !item.childNode) {
            // 设置父元素所占
            this.handleSetCol(this.treeMap[item.parentId], rank + 1)
          }
          if (Array.isArray(item.childNode)) {
            nextQueue = nextQueue.concat(item.childNode)
          }
        }
        queue = JSON.parse(JSON.stringify(nextQueue))
        nextQueue = []
        rank++
        // 确定循环的key
        this.titleKey.push(`key${rank}`)
        // 确定循环的对象
        this.backUpItem[`key${rank}`] = ''
      }
      Object.values(this.treeMap).forEach((item, index) => {
        !item.parentId && sortList(item.childNode)
      })
    },
    initItem(item, ret) {
      ret[`key${item.rank}`] = item.projectName
      item.isSet = true
      if (!item.parentId) {
        ret.index = item.projectName
      }
      return item.parentId && !this.treeMap[item.parentId].isSet
        ? this.initItem(this.treeMap[item.parentId], ret)
        : ret
    },
    getRootId(id) {
      if (!this.treeMap[id].parentId) {
        return this.treeMap[id]
      }
      return this.getRootId(this.treeMap[id].parentId)
    },
    initTableList() {
      const result = []
      let currentIndex = 0
      this.resultList.forEach(item => {
        const ret = {
          ...this.backUpItem,
          money: item.money ? item.money : 0,
          remark: item.remark,
          id: item.id
        }
        // 判断有多少个rank = 1 的项 就有多少个item
        if (
          !this.treeMap[item.parentId].isIndex &&
          this.treeMap[item.parentId].rank === 1
        ) {
          ++currentIndex
          this.treeMap[item.parentId].isIndex = true
        }
        ret.repertory = currentIndex
        result.push(this.initItem(item, ret))
      })
      console.log(result, 'result')
      return result
    },
    getSummaries(param) {
      const { columns, data } = param
      const sums = []
      columns.forEach((column, index) => {
        if (index === this.titleKey.length + 1) {
          let ret = 0
          data.forEach(item => {
            ret += item.money
          })
          sums[index] = ret
        } else if (index !== 0) {
          sums[index] = ''
        } else {
          sums[index] = '合计'
        }
      })
      this.$nextTick(() => {
        this.$refs['table'].doLayout()
      })
      return sums
    },
    // 写到请求后端数据里
    transformationList() {
      // this.projectForecast 后端请求到的树形数据
      this.initData(this.projectForecast)
      const tableList = this.initTableList()
      for (let i = 0; i < tableList.length; i++) {
        for (let j = 0; j < this.titleKey.length + 6; j++) {
          console.log(this.matrixMap[`row${i}-col${j}`], 'aaaa')
          if (j === 0) {
            if (this.nameMap[tableList[i]['index']]) {
              this.matrixMap[`row${i}-col${j}`] = [
                this.nameMap[tableList[i]['index']].row - 1,
                1
              ]
            } else {
              this.matrixMap[`row${i}-col${j}`] = [0, 0]
            }
          } else if (j > 0 && j <= this.titleKey.length) {
            if (tableList[i][`key${j}`]) {
              this.matrixMap[`row${i}-col${j}`] = [
                this.nameMap[tableList[i][`key${j}`]].row > 1
                  ? this.nameMap[tableList[i][`key${j}`]].row - 1
                  : this.nameMap[tableList[i][`key${j}`]].row,
                this.nameMap[tableList[i][`key${j}`]].col
              ]
            } else {
              this.matrixMap[`row${i}-col${j}`] = [0, 0]
            }
          } else {
            this.matrixMap[`row${i}-col${j}`] = [1, 1]
          }
        }
      }
      this.tableList = tableList
    }
  }
View Code
 注意: 树形数据 首层不能有parentId,
 
a