手写多层级树形结构Vue3 + handsontable

效果如下:
在这里插入图片描述

<template>
  <t-card>
    <t-form>
      <div>
        <div class="category">一:项目基本信息</div>
        <rn-form ref="form" ref-value="form" colon :data="formData" style="padding: 1% 3%" :form-item-config="formItemConfig" :rules="rules"></rn-form>
      </div>
      <div>
        <t-button @click="getDataSource">获取数据源</t-button>
        <t-button @click="setDataSource">回显数据</t-button>
        <t-button @click="setTreeDataSource">回显多层级树形结构数据</t-button>
        <t-button @click="setMergeCells">合并单元格</t-button>
        <div class="category">二:建设内容</div>
        <hot-table ref="hotTableComponent" width="100%" height="auto" :settings="settings"></hot-table>
      </div>
    </t-form>
  </t-card>
</template>
<script lang='ts'>
import { HotTable } from '@handsontable/vue3'
import HyperFormula from 'hyperformula'
import RnForm from '@/components/form/RnForm.vue'

const data = [{ id: 1, xh: '(一)', content: '建安工程', isEdit: false, remark: '=(G1+H1)', price: '=SUM(G2:G11)', invest: '=SUM(H2:H11)', action: '', pid: '' }, { id: 1710405265802, xh: '(一)', content: '测试', isEdit: true, pid: 1, remark: '=(G2+H2)', price: 2, invest: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405266212, xh: '(一)', content: '测试', isEdit: true, pid: 1, remark: '=(G3+H3)', price: 3, invest: 2, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405266699, xh: '(一)', content: '测试', isEdit: true, remark: '=(G4+H4)', price: 4, invest: 3, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405273518, xh: '(一)', content: '测试', isEdit: true, remark: '=(G5+H5)', price: 2, invest: 2, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405278959, xh: '(一)', content: '测试', isEdit: true, remark: '=(G6+H6)', price: 1, invest: 3, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934462, xh: '(一)', content: '测试', isEdit: true, remark: '=(G7+H7)', price: 4, invest: 4, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934644, xh: '(一)', content: '测试', isEdit: true, remark: '=(G8+H8)', price: 432, invest: 343, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934823, xh: '(一)', content: '测试', isEdit: true, remark: '=(G9+H9)', price: 4, invest: 234, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405935029, xh: '(一)', content: '测试', isEdit: true, remark: '=(G10+H10)', price: 34, invest: 324, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405935221, xh: null, content: '测试', isEdit: true, remark: '=(G11+H11)', price: 32, invest: 32, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 2, xh: '(二)', content: '田间工程', isEdit: false, remark: '=(G12+H12)', price: '=SUM(G13:G14)', invest: '=SUM(H13:H14)' }, { id: 1710405969779, xh: '(二)', content: '田间工程', isEdit: true, remark: '=(G13+H13)', price: 44, invest: 432, action: null, pid: 2, type: '弹窗成功', scale: '工作.txt' }, { id: 1710405970575, xh: '(二)', content: '田间工程', isEdit: true, remark: '=(G14+H14)', price: 32, invest: 432, action: null, pid: 2, scale: '工作.txt' }, { id: 3, xh: '(三)', content: '仪器设备购置', isEdit: false }, { id: 4, xh: '(四)', content: '其他', isEdit: false }, { id: 5, xh: '合计', isEdit: false }]

let _this = null
const FORM_ITEM_CONFIG = [
  { hidden: false, name: 'projectName', label: '项目编号', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入项目名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '项目名称', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '申报单位', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '申报文件', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '建设性质', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '建设单位', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '建设年限', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '建设地点(省、市、县、镇)', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
  { hidden: false, name: 'declareFileName', label: '主要建设内容 及规模', componentType: 't-input', dataType: '', colProps: { span: 6 }, componentProps: { type: 'text', placeholder: '请输入申报文件名称' }, formItemProps: { labelWidth: '120px' } },
]
export default {
  name: 'DeclareGuide',
  components: { RnForm, HotTable },
  // eslint-disable-next-line max-lines-per-function
  data() {
    return {
      settings: {
        language: 'zh-CN', // 官方汉化
        licenseKey: 'non-commercial-and-evaluation', // 去除底部非商用声明
        colHeaders: ['A', 'B', '建设内容C', '建筑形式D', '规模(数量)E', '单位F', '单价(元)G', '投资估算(万元)H', '备注I'],
        columns: [
          { data: 'action',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit && instance.getSourceDataAtRow (row).content !== '合计') {
                td.innerHTML = `<img src="/src/assets/button-img/btn-add.svg" style="width: 20px;height: 20px;cursor: pointer;margin-top: 3px" title="添加" οnclick="addRow(${row},${col})">`
              } else {
                td.innerHTML = `<img src="/src/assets/button-img/btn-add.svg" style="width: 20px;height: 20px;cursor: pointer;margin-top: 3px" title="添加" οnclick="addRow(${row},${col})">&nbsp;`
                td.innerHTML += `<img src="/src/assets/button-img/btn-cut.svg" style="width: 20px;height: 20px;cursor: pointer;margin-top: 3px" title="删除" οnclick="deleteRow(${row})">`
              }
              td.style.height = '100%'
              td.style.textAlign = 'center'
              td.style.verticalAlign = 'middle'
              cellProperties.readOnly = true
              return td
            } },
          { data: 'xh',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.style.verticalAlign = 'middle'
              } else {

              }
              td.innerHTML = value
              return td
            } },
          { data: 'content',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.style.verticalAlign = 'middle'
                cellProperties.readOnly = true
              } else {

              }
              if (_this) {
                // 是否显示toggle图标
                const showToggleIcon = _this.filterChildrenLength(instance.getSourceDataAtRow(row).id)
                const { pid } = instance.getSourceDataAtRow(row)
                const spaceIndex = _this.filterParent(pid, 0)
                let paddingElement = ''
                if (spaceIndex > 0) {
                  paddingElement = `${5 * spaceIndex}px`
                }
                if (showToggleIcon) {
                  const toggle = _this.filterToggleStatus(row)
                  if (toggle) {
                    td.innerHTML = `<div style="cursor: pointer;height: 100%;display: flex" οnclick="toggoleRow(${instance.getSourceDataAtRow(row).id},${row},this)"><img src="/src/assets/button-img/up.svg" style="width: 12px;height: 100%;margin-right:5px;padding-left: ${paddingElement};" title="展开" ><div style="height: 100%;word-break: break-all;display:flex;align-items:center;">${value}</div></div>`
                  } else {
                    td.innerHTML = `<div style="cursor: pointer;height: 100%;display: flex" οnclick="toggoleRow(${instance.getSourceDataAtRow(row).id},${row},this)"><img src="/src/assets/button-img/down.svg" style="width: 12px;height: 100%;margin-right:5px;padding-left: ${paddingElement}; " title="收缩"><div style="height: 100%;word-break: break-all;display:flex;align-items:center;">${value}</div></div>`
                  }
                } else {
                  paddingElement = `${7 * spaceIndex}px`
                  td.innerHTML = `<div style="height: 100%;word-break: break-all;display:flex;align-items:center;padding-left: ${paddingElement};">${value || ''}</div>`
                }
              } else {
                td.innerHTML = value
              }
              // eslint-disable-next-line no-bitwise
              return td & cellProperties & value
            } },
          { data: 'type',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.innerHTML = value || ''
              } else {
                td.innerHTML = `<div class="htAutocompleteArrow" aria-hidden="true"><img src="/src/assets/button-img/open-window.svg" style="width: 20px;height: 20px;margin-top: 3px"></div><div style="cursor: pointer;height: 100%;width: 100%" οnclick="showModals(${row}, ${col})">${value || ''}</div>`
              }
              return td
            } },
          { data: 'scale',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.innerHTML = `${value || ''}`
              } else if (value) {
                td.innerHTML = `<div class="htAutocompleteArrow" ><img src="/src/assets/button-img/upload.svg" style="width: 15px;height: 15px;margin-top: 3px"></div><div style="cursor: pointer;width: 100%;height: 100%" οnclick="selectFile(${row},${col})"><input type="file" id="myFile_${row}_${col}" hidden οnchange="beforeUpload(this)">${value || ''}&nbsp;&nbsp;<img src="/src/assets/button-img/delete.svg" style="cursor:pointer;width: 10px;height: 10px;" title="删除" οnclick="deleteFile(${row},${col})"></div>`
              } else {
                td.innerHTML = `<div class="htAutocompleteArrow" ><img src="/src/assets/button-img/upload.svg" style="width: 15px;height: 15px;margin-top: 3px"></div><div style="cursor: pointer;width: 100%;height: 100%" οnclick="selectFile(${row},${col})"><input type="file" id="myFile_${row}_${col}" hidden οnchange="beforeUpload(this)">${value || ''}</div>`
              }
              return td
            } },
          { data: 'unit',
            type: 'dropdown',
            source: ['处', '个', '口', '立方米', '米', '亩', '平方米', '台', '套', '项', '株', '座'],
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.innerHTML = `${value || ''}`
              } else {
                td.innerHTML = `<div class="htAutocompleteArrow" >▼</div>${value || ''}`
              }
              return td
            } },
          { data: 'price',
            type: 'numeric',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.style.color = 'red'
                td.style.fontWeight = 'bold'
                if (value && typeof (value) === 'string' && value.indexOf('=') !== -1) {
                  instance.setDataAtCell(row, col, value)
                  td.innerHTML = 0
                } else {
                  td.innerHTML = `${value === '#REF!' ? 0 : value || 0}`
                }
              } else {
                td.innerHTML = `<div style="height:100%;width: 0%;float: right;display: flex;align-items: center;font-weight: bold">$</div>${value || ''}`
              }
              td.style.paddingRight = '20px'
              td.style.wordBreak = 'break-all'
              return td
            } },
          { data: 'invest',
            type: 'numeric',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              if (!instance.getSourceDataAtRow (row)?.isEdit) {
                td.style.color = 'red'
                td.style.fontWeight = 'bold'
                if (value && typeof (value) === 'string' && value.indexOf('=') !== -1) {
                  instance.setDataAtCell(row, col, value)
                  td.innerHTML = 0
                } else {
                  td.innerHTML = `${value === '#REF!' ? 0 : value || 0}`
                }
              } else {
                td.innerHTML = `<div style="height:100%;width: 0%;float: right;display: flex;align-items: center;font-weight: bold">¥</div>${value || ''}`
              }
              td.style.paddingRight = '20px'
              td.style.wordBreak = 'break-all'
              return td
            } },
          { data: 'remark',
            type: 'text',
            renderer(instance, td, row, col, prop, value, cellProperties) {
              td.style.color = 'red'
              td.style.fontWeight = 'bold'
              //
              if (value && typeof (value) === 'string' && value.indexOf('=') !== -1) {
                instance.setDataAtCell(row, col, value)
                td.innerHTML = 0
              } else {
                td.innerHTML = `${value === '#REF!' ? 0 : value || 0}`
              }
              td.style.paddingRight = '20px'
              td.style.wordBreak = 'break-all'
              return td
            } },
        ],
        data: [
          { id: 1, xh: '(一)', content: '建安工程', isEdit: false },
          { id: 2, xh: '(二)', content: '田间工程', isEdit: false },
          { id: 3, xh: '(三)', content: '仪器设备购置', isEdit: false },
          { id: 4, xh: '(四)', content: '其他', isEdit: false },
          { id: 5, xh: '合计', isEdit: false },
        ],
        currentRowClassName: 'currentRow', // 突出显示行
        currentColClassName: 'currentCol', // 突出显示列
        autoWrapRow: false, // 自动换行
        trimWhitespace: false, // 去除空格
        colWidths: [30, 40, 100, 150, 150, 80, 80, 100, 100, 150],
        stretchH: 'all',
        renderAllRows: false,
        rowHeaders: false, // 列序号
        formulas: {
          engine: HyperFormula, // 引入excel公式
        },
        copyable: true, // 允许键盘复制
        copyPaste: true, // 复制粘贴
        fixedColumnsLeft: 0, // 固定左边列数
        fixedRowsTop: 0, // 固定上边列数
        manualColumnResize: true,
        hiddenRows: {
          rows: [],
        },
        mergeCells: [
        ],
      },
      formItemConfig: [],
    }
  },
  computed: {
  },
  mounted() {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    _this = this
    _this.initFormItemConfig()
    window.addRow = _this.addRow
    window.deleteRow = _this.deleteRow
    window.toggoleRow = _this.toggoleRow
    window.showModals = _this.showModals
    window.selectFile = _this.selectFile
    window.beforeUpload = _this.beforeUpload
    window.deleteFile = _this.deleteFile
  },
  methods: {
    filterChildrenLength(id) {
      const sourceData = _this.$refs.hotTableComponent.hotInstance.getSourceData()
      const filterChild = sourceData.filter((item) => item.pid === id)
      return filterChild.length > 0
    },
    filterToggleStatus(row) {
      const rows = _this.$refs.hotTableComponent.hotInstance.getPlugin('hiddenRows').getHiddenRows()
      const filter = rows.filter((item) => item === row + 1)
      return filter.length > 0
    },
    initFormItemConfig() {
      _this.formItemConfig = FORM_ITEM_CONFIG
    },
    addRow(row, col) {
      // 获取表格源数据
      // _this.settings.maxRows = _this.settings.maxRows + 1
      // _this.$refs.hotTableComponent.hotInstance.updateSettings({ maxRows: Number(_this.settings.maxRows), })
      // _this.$refs.hotTableComponent.hotInstance.getPlugin('formulas').engine.updateConfig({ maxRows: Number(_this.settings.maxRows) })
      const sourceData = _this.$refs.hotTableComponent.hotInstance.getSourceData()
      // 获取add父节点行数据
      const { id } = _this.$refs.hotTableComponent.hotInstance.getSourceDataAtRow(row)

      const filterChild = sourceData.filter((item) => item.pid === id)
      let alertRowIndex = row
      // 如果有子节点,就插入到子节点后面,没有的话,插入父节点后面
      if (filterChild.length > 0) {
        alertRowIndex = row + filterChild.length
      }
      // 添加一行空白的数据
      _this.$refs.hotTableComponent.hotInstance.alter('insert_row_below', alertRowIndex)
      // 拿到刚才新增的数据,赋值
      const alertRow = _this.$refs.hotTableComponent.hotInstance.getSourceDataAtRow(alertRowIndex + 1)
      alertRow.id = new Date().getTime()
      alertRow.pid = id
      alertRow.isEdit = true
      // 赋值后,将新数据替换handsontable源数据
      const newSourceData = _this.$refs.hotTableComponent.hotInstance.getSourceData()
      newSourceData.splice(alertRowIndex + 1, 1, alertRow)
      // 更新handsontable源数据
      _this.$refs.hotTableComponent.hotInstance.loadData(newSourceData)
      setTimeout(() => {
        _this.$refs.hotTableComponent.hotInstance.setDataAtCell(row, 6, `=SUM(g${row + 2}:g${alertRowIndex + 2})`)
        _this.$refs.hotTableComponent.hotInstance.setDataAtCell(row, 7, `=SUM(h${row + 2}:h${alertRowIndex + 2})`)
        _this.$refs.hotTableComponent.hotInstance.setDataAtCell(row, 8, `=(G${row + 1}+H${row + 1})`)
        _this.$refs.hotTableComponent.hotInstance.setDataAtCell(alertRowIndex + 1, 8, `=(G${alertRowIndex + 2}+H${alertRowIndex + 2})`)
      }, 100)
    },
    deleteRow(row) {
      _this.$refs.hotTableComponent.hotInstance.alter('remove_row', row)
      // 获取表格源数据
      // const afterMaxRows = _this.settings.maxRows - 1
      // _this.$refs.hotTableComponent.hotInstance.updateSettings({ maxRows: afterMaxRows, })
    },
    toggoleRow(selfId, row, e) {
      const hideArr = []
      const plugin = _this.$refs.hotTableComponent.hotInstance.getPlugin('hiddenRows')
      const sourceData = _this.$refs.hotTableComponent.hotInstance.getSourceData()
      const filterSelfChild = []
      const loopFilterParent = function (id) {
        const filterNextChild = sourceData.filter((item) => item.pid === id)
        if (filterNextChild.length > 0) {
          for (const filterChildElement of filterNextChild) {
            filterSelfChild.push(filterChildElement)
            loopFilterParent(filterChildElement.id)
          }
        }
      }
      loopFilterParent(selfId)
      for (let i = row + 1; i <= row + filterSelfChild.length; i++) {
        hideArr.push(i)
      }
      if (e.children[0].src.indexOf('down') !== -1) {
        e.src = e.children[0].src.replace('down', 'up')
        plugin.hideRows(hideArr)
      } else {
        e.src = e.children[0].src.replace('up', 'down')
        plugin.showRows(hideArr)
      }
      _this.$refs.hotTableComponent.hotInstance.render()
    },
    showModals(row, col) {
      const $dialog = this.$dialog({
        header: 'Dialog-Plugin',
        body: 'Plugin 方式创建新弹窗',
        className: 't-dialog-new-class1 t-dialog-new-class2',
        style: 'color: rgba(0, 0, 0, 0.6)',
        onConfirm: () => {
          _this.$refs.hotTableComponent.hotInstance.setDataAtCell(row, col, '弹窗成功')
          $dialog.hide()
        },
      })
    },
    selectFile(row, col) {
      const element = document.getElementById(`myFile_${row}_${col}`)
      element.click()
    },
    beforeUpload(event) {
      const file = event.files[0]
      const arr = event.id.split('_')
      _this.$refs.hotTableComponent.hotInstance.setDataAtCell(Number(arr[1]), Number(arr[2]), file.name)
    },
    deleteFile(row, col) {
      _this.$refs.hotTableComponent.hotInstance.setDataAtCell(row, col, null)
    },
    getDataSource() {
      console.log(_this.$refs.hotTableComponent.hotInstance.getSourceData())
    },
    setDataSource() {
      const data = [{ id: 1, xh: '(一)', content: '建安工程', isEdit: false, remark: '=(G1+H1)', price: '=SUM(G2:G11)', invest: '=SUM(H2:H11)', action: '', pid: '' }, { id: 1710405265802, xh: '(一)', content: '测试', isEdit: true, pid: 1, remark: '=(G2+H2)', price: 2, invest: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405266212, xh: '(一)', content: '测试', isEdit: true, pid: 1, remark: '=(G3+H3)', price: 3, invest: 2, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405266699, xh: '(一)', content: '测试', isEdit: true, remark: '=(G4+H4)', price: 4, invest: 3, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405273518, xh: '(一)', content: '测试', isEdit: true, remark: '=(G5+H5)', price: 2, invest: 2, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405278959, xh: '(一)', content: '测试', isEdit: true, remark: '=(G6+H6)', price: 1, invest: 3, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934462, xh: '(一)', content: '测试', isEdit: true, remark: '=(G7+H7)', price: 4, invest: 4, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934644, xh: '(一)', content: '测试', isEdit: true, remark: '=(G8+H8)', price: 432, invest: 343, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405934823, xh: '(一)', content: '测试', isEdit: true, remark: '=(G9+H9)', price: 4, invest: 234, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405935029, xh: '(一)', content: '测试', isEdit: true, remark: '=(G10+H10)', price: 34, invest: 324, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 1710405935221, xh: null, content: '测试', isEdit: true, remark: '=(G11+H11)', price: 32, invest: 32, action: null, pid: 1, type: '弹窗成功', scale: '新建文本文档 (2).txt', unit: '平方米' }, { id: 2, xh: '(二)', content: '田间工程', isEdit: false, remark: '=(G12+H12)', price: '=SUM(G13:G14)', invest: '=SUM(H13:H14)' }, { id: 1710405969779, xh: '(二)', content: '田间工程', isEdit: true, remark: '=(G13+H13)', price: 44, invest: 432, action: null, pid: 2, type: '弹窗成功', scale: '工作.txt' }, { id: 1710405970575, xh: '(二)', content: '田间工程', isEdit: true, remark: '=(G14+H14)', price: 32, invest: 432, action: null, pid: 2, scale: '工作.txt' }, { id: 3, xh: '(三)', content: '仪器设备购置', isEdit: false }, { id: 4, xh: '(四)', content: '其他', isEdit: false }, { id: 5, xh: '合计', isEdit: false }]
      _this.$refs.hotTableComponent.hotInstance.loadData(data)
      window.ht = _this.$refs.hotTableComponent.hotInstance
      setTimeout(() => {
        _this.$refs.hotTableComponent.hotInstance.render()
      }, 100)
    },
    setTreeDataSource() {
      const data = [{ id: 1, xh: '(一)', content: '建安工程', isEdit: false, remark: '=(G1+H1)', price: '=SUM(G2:G11)', invest: '=SUM(H2:H11)', action: '', pid: '' }, { id: 1710488757149, xh: null, content: '二级建安工程', isEdit: true, pid: 1, remark: '=(G2+H2)', price: '=SUM(G3:G3)', invest: '=SUM(H3:H3)' }, { id: 1710488770271, xh: null, content: '三级建安工程', isEdit: true, remark: '=(G3+H3)', price: '=SUM(G4:G4)', invest: '=SUM(H4:H4)', pid: 1710488757149 }, { id: 1710488779144, xh: null, content: '四级建安工程', isEdit: true, remark: '=(G4+H4)', price: '=SUM(G5:G5)', invest: '=SUM(H5:H5)', pid: 1710488770271 }, { id: 1710488784815, xh: null, content: '五级建安工程', isEdit: true, remark: '=(G5+H5)', price: '=SUM(G6:G6)', invest: '=SUM(H6:H6)', pid: 1710488779144 }, { id: 1710488790893, xh: null, content: '六级建安工程', isEdit: true, remark: '=(G6+H6)', price: '=SUM(G7:G7)', invest: '=SUM(H7:H7)', pid: 1710488784815 }, { id: 1710488796686, xh: null, content: '七级建安工程', isEdit: true, remark: '=(G7+H7)', price: '=SUM(G8:G8)', invest: '=SUM(H8:H8)', pid: 1710488790893 }, { id: 1710488803610, xh: null, content: '八级建安工程', isEdit: true, remark: '=(G8+H8)', price: '=SUM(G9:G9)', invest: '=SUM(H9:H9)', pid: 1710488796686 }, { id: 1710488811848, xh: null, content: '九级建安工程', isEdit: true, remark: '=(G9+H9)', price: '=SUM(G10:G10)', invest: '=SUM(H10:H10)', pid: 1710488803610 }, { id: 1710488820012, xh: null, content: '十级建安工程', isEdit: true, remark: '=(G10+H10)', price: null, invest: null, pid: 1710488811848 }, { id: 1710488763836, xh: null, content: '二级建安工程', isEdit: true, pid: 1, remark: '=(G11+H11)' }, { id: 2, xh: '(二)', content: '田间工程', isEdit: false }, { id: 3, xh: '(三)', content: '仪器设备购置', isEdit: false }, { id: 4, xh: '(四)', content: '其他', isEdit: false }, { id: 5, xh: '合计', isEdit: false }]
      _this.$refs.hotTableComponent.hotInstance.loadData(data)
      window.ht = _this.$refs.hotTableComponent.hotInstance
      setTimeout(() => {
        _this.$refs.hotTableComponent.hotInstance.render()
      }, 100)
    },
    setMergeCells() {
      _this.settings.mergeCells.push({ row: 1, col: 1, rowspan: 1, colspan: 3 }, { row: 2, col: 2, rowspan: 2, colspan: 1 })
    },

    filterParent(pid, spaceIndex) {
      let resultIndex = spaceIndex
      if (!pid) {
        return resultIndex
      }
      const loopFilterParent = function (pid, spaceIndex) {
        const sourceData = _this.$refs.hotTableComponent.hotInstance.getSourceData()
        const filterChild = sourceData.filter((item) => item.id === pid)
        if (filterChild.length > 0) {
          loopFilterParent(filterChild[0].pid, spaceIndex + filterChild.length)
        } else {
          resultIndex = spaceIndex
        }
      }
      loopFilterParent(pid, resultIndex)
      return resultIndex
    },
  },

}
</script>

<style lang="less" scoped>
  .category{
    font-weight: bold;
    font-size: large;
  }
</style>

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值