<template>
  <vxe-table
     height="auto"
     border
    :column-config="{resizable: true}"
    :scroll-y="{enabled: false}"
    :span-method="rowspanMethod"
    :data="demo1.tableData">
    <vxe-column field="name1" title="功能模块">
      <template #default="{ row }">
        {{ row.name1 }}
      </template>
    </vxe-column>
    <vxe-column field="name2" title="详细功能">
      <template #default="{ row }">
        {{ row.name2 }}
      </template>
    </vxe-column>
    <vxe-column field="name3" title="权限类型">
      <template #default="{ row }">
        {{ row.name3 }}
      </template>
    </vxe-column>
    <vxe-column field="name4" title="权限列表">
      <template #default="{ row }">
        <vxe-checkbox v-model="row.check4" @change="check4ChangeEvent(row, row.check4)">{{ row.name4 }}</vxe-checkbox>
      </template>
    </vxe-column>
  </vxe-table>

</template>

<script lang="tsx" setup>
import { ref, reactive } from 'vue'
import { VxeTablePropTypes } from 'vxe-table'
import XEUtils from 'xe-utils'

const demo1 = reactive({tableData: [] as any[] })


  const check4ChangeEvent = (row: any, checked: boolean) => {
    let childList = demo1.tableData.filter(item => item.id3 === row.id3 && item.name4 === row.name4)
    childList.forEach(item => {
      item.check4 = checked
    })
    childList = demo1.tableData.filter(item => item.id3 === row.id3)
    const isChecked3 = childList.every(item => item.check4)
    childList.forEach(item => {
      item.check3 = isChecked3
    })
    childList = demo1.tableData.filter(item => item.id2 === row.id2)
    const isChecked2 = childList.every(item => item.check3)
    childList.forEach(item => {
      item.check2 = isChecked2
    })
    childList = demo1.tableData.filter(item => item.id1 === row.id1)
    const isChecked1 = childList.every(item => item.check2)
    childList.forEach(item => {
      item.check1 = isChecked1
    })
  }

  const check3ChangeEvent = (row: any, checked: boolean) => {
    let childList = demo1.tableData.filter(item => item.id2 === row.id2 && item.name3 === row.name3)
    childList.forEach(item => {
      item.check3 = checked
    })
    childList = demo1.tableData.filter(item => item.id3 === row.id3)
    childList.forEach(item => {
      check4ChangeEvent(item, checked)
    })
  }

  const check2ChangeEvent = (row: any, checked: boolean) => {
    let childList = demo1.tableData.filter(item => item.id1 === row.id1 && item.name2 === row.name2)
    childList.forEach(item => {
      item.check2 = checked
    })
    childList = demo1.tableData.filter(item => item.id2 === row.id2)
    childList.forEach(item => {
      check3ChangeEvent(item, checked)
    })
  }

  const check1ChangeEvent = (row: any, checked: boolean) => {
    let childList = demo1.tableData.filter(item => item.name1 === row.name1)
    childList.forEach(item => {
      item.check1 = checked
    })
    childList = demo1.tableData.filter(item => item.id1 === row.id1)
    childList.forEach(item => {
      check2ChangeEvent(item, checked)
    })
  }

  const getList = () => {
    const list = [
      { id: '10000', parentId: null, name: '账号管理' },
      { id: '11000', parentId: '10000', name: '用户管理' },
      { id: '11100', parentId: '11000', name: '查看' },
      { id: '11110', parentId: '11100', name: '用户列表' },
      { id: '11200', parentId: '11000', name: '编辑' },
      { id: '11210', parentId: '11200', name: '用户列表' },
      { id: '11220', parentId: '11200', name: '新增用户' },
      { id: '11300', parentId: '11000', name: '操作' },
      { id: '11310', parentId: '11300', name: '新增' },
      { id: '11320', parentId: '11300', name: '删除' },
      { id: '11330', parentId: '11300', name: '修改' },
      { id: '12000', parentId: '10000', name: '角色管理' },
      { id: '12100', parentId: '12000', name: '查看' },
      { id: '12110', parentId: '12100', name: '角色列表' },
      { id: '12200', parentId: '12000', name: '编辑' },
      { id: '122100', parentId: '12200', name: '角色列表' },
      { id: '12220', parentId: '12200', name: '新增角色' },
      { id: '12300', parentId: '12000', name: '操作' },
      { id: '12310', parentId: '12300', name: '新增' },
      { id: '12320', parentId: '12300', name: '删除' },
      { id: '12330', parentId: '12300', name: '修改' },
      { id: '20000', parentId: null, name: '个人中心' },
      { id: '21000', parentId: '20000', name: '个性化设置' },
      { id: '21100', parentId: '21000', name: '查看' },
      { id: '21110', parentId: '21100', name: '信息列表' },
      { id: '21200', parentId: '21000', name: '操作' },
      { id: '21210', parentId: '21200', name: '重置信息' },
      { id: '22000', parentId: '20000', name: '账户管理' },
      { id: '22100', parentId: '22000', name: '查看' },
      { id: '22110', parentId: '22100', name: '账户余额' },
      { id: '22120', parentId: '22100', name: '帐变记录' }
    ]
    return list
  }

  // 将普通树结构转换为横向树列表
  const toColTreeData = (treeData: any[]) => {
    const options = { children: 'children' }
    const list: any[] = []
    const keyMap: any = {}
    XEUtils.eachTree(treeData, (item, index, result, paths, parent) => {
      keyMap[item.id] = item
      item.keys = parent ? parent.keys.concat([item.id]) : [item.id]
      if (!item.children || !item.children.length) {
        const row: any = {}
        item.keys.forEach((key: any, index: number) => {
          const level = index + 1
          const obj = keyMap[key]
          row[`check${level}`] = false
          row[`id${level}`] = obj.id
          row[`name${level}`] = obj.name
        })
        list.push(row)
      }
    }, options)
    demo1.tableData = list
  }

  // 通用行合并函数（将相同多列数据合并为一行）
  const rowspanMethod: VxeTablePropTypes.SpanMethod = ({ row, _rowIndex, column, visibleData }) => {
    const fields = ['name1', 'name2', 'name3']
    const cellValue = row[column.field]
    if (cellValue && fields.includes(column.field)) {
      const prevRow = visibleData[_rowIndex - 1]
      let nextRow = visibleData[_rowIndex + 1]
      if (prevRow && prevRow[column.field] === cellValue) {
        return { rowspan: 0, colspan: 0 }
      } else {
        let countRowspan = 1
        while (nextRow && nextRow[column.field] === cellValue) {
          nextRow = visibleData[++countRowspan + _rowIndex]
        }
        if (countRowspan > 1) {
          return { rowspan: countRowspan, colspan: 1 }
        }
      }
    }
  }

  const treeData = XEUtils.toArrayTree(getList())
  toColTreeData(treeData)




</script>