Element UI 树形表格

1.结构

<!-- 表格 -->
    <div class="table-con">
        <div class="clearfix search-bar">
            <div class="fl">
                <el-input v-model="serviceName" placeholder="请输入服务名称"></el-input>
            </div>
            <div class="fl">
                <el-select v-model="serviceRoleId" placeholder="请选择服务角色">
                  <el-option v-for="item in serviceRole" :key="item.id" :label="item.name" :value="item.id">
                  </el-option>
                </el-select>
            </div>
            <div class="fl">
                <el-select v-model="serviceTypeId" placeholder="请选择服务类型">
                  <el-option v-for="item in serviceType" :key="item.id" :label="item.name" :value="item.id">
                  </el-option>
                </el-select>
            </div>
            <div class="fl">
                <el-button type="primary" @click="getPermissionList">查询</el-button>
                <el-button type="primary" @click="addService">新增服务</el-button>
                <!-- <el-button type="primary" @click="batchDeleteService">批量删除</el-button> -->
            </div>
        </div>
        <el-table ref="serviceList" border :data="serviceList" tooltip-effect="dark" style="width: 100%" class="serviceList" @selection-change="multiSelect" :row-class-name="rowClassNameHandler">
            <el-table-column type="selection"></el-table-column>
            <el-table-column label="名称" width="200" align="left">
                <template slot-scope="scope">
                    <span :style="{marginLeft: scope.row.level * 23 + 'px'}">&ensp;</span>
                    <i v-if="scope.row.showChildren" :class="{'el-icon-folder-opened':scope.row.showChildren, 'el-icon-tickets':!scope.row.hasChildren}" @click="onExpand(scope.row)" :style="{cursor:scope.row.hasChildren ? 'pointer' : 'normal'}" ></i>
                    <i v-else :class="{'el-icon-folder':scope.row.hasChildren, 'el-icon-tickets':!scope.row.hasChildren}" @click="onExpand(scope.row)" :style="{cursor:scope.row.hasChildren ? 'pointer' : 'normal'}" ></i>
                    <span :data-level="scope.row.level" :style="{marginLeft: 4 + 'px'}">{{ scope.row.name }}</span>

                </template>
            </el-table-column>
            <el-table-column prop="icon" label="图标" align="center" show-overflow-tooltip>
                <template slot-scope="scope">
                    <img class="icon-img" :src="scope.row.icon" alt="图标">
                </template>
            </el-table-column>
            <el-table-column prop="permissionTypeName" label="类型" align="center" show-overflow-tooltip></el-table-column>
            <el-table-column prop="permission" label="权限码" align="center" show-overflow-tooltip></el-table-column>
            <el-table-column prop="roleName" label="使用角色" align="center" show-overflow-tooltip></el-table-column>
            <el-table-column label="所属系统" align="center" show-overflow-tooltip>
                <template slot-scope="scope">
                    <div>
                        <span v-if="scope.row.sysId == 1">信息发布系统</span>
                        <span v-else>OA</span>
                    </div>
                </template>
            </el-table-column>
            <el-table-column prop="url" label="地址" align="center" show-overflow-tooltip></el-table-column>
            <el-table-column prop="desc" label="备注信息" align="center" show-overflow-tooltip></el-table-column>
            <el-table-column label="操做" align="center"> 
                <template slot-scope="scope">
                    <div>
                        <p>
                            <el-button @click="addChildrenService(scope.row)" type="text" size="small">新增子服务</el-button>
                        </p>
                        <el-button @click="modifyService(scope.row)" type="text" size="small">修改</el-button>
                        <el-button @click="deleteService(scope.row)" type="text" size="small">删除</el-button>
                    </div>
                </template>
            </el-table-column>
        </el-table>
        <!-- 分页 -->
        <!-- <div style="text-align: center;"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="currentPage" :page-size="pageSize" layout="total, prev, pager, next" :total="listTotal"> </el-pagination> </div> -->
    </div>
复制代码

2.方法

<script>
import { permissionAllList } from '@/request/api';
export default {
    name: 'serviceApplication',
    data() {
      return {
          serviceName: '',        //搜索服务名称
          serviceRoleId: '',      //服务角色id
          serviceTypeId: '',      //服务类型id
          serviceList: [],        //全部服务列表
          currentPage: 1,         //当前页
          pageSize: 10,           //每页的数量
          listTotal: 0,           //总页数
          allSelectedItems: [],   //多选数据
          
      }
    },
    mounted() {
        this.getPermissionList();
    },
    methods: {
        //获取全部服务列表
        getPermissionList() {
            let param = {
                name: this.serviceName,
                roleId: this.serviceRoleId,
                typeId: this.serviceTypeId,
                // pageNum: this.currentPage,
                // pageSize: this.pageSize
            }
            permissionAllList(param).then(res => {
                if(res.code == 0){
                    // console.log(res)
                    let result = res.data;
                    let resultArr = this.processLevelServiceList(result)
                    this.serviceList = resultArr;
                    this.listTotal = res.data.total;
                }else{
                    this.$message({
                        message: res.msg,
                        type: 'warning'
                    })
                }
            })
        },
        //分页方法
        handleSizeChange(val) {
            console.log(`每页 ${val} 条`);
        },
        handleCurrentChange(val) {
            console.log(`当前页: ${val}`);
            this.getPermissionList();
        },
        //服务应用数据处理
        processLevelServiceList(dataArray) {
            let that = this
            let resultArray = [] // 一级栏目
            let level = 1
            for (let i = 0; i < dataArray.length; i++) {
                let item = dataArray[i]
                // 查找一级分类
                if (item.parentId === 0) {
                    item['level'] = level
                    resultArray.push(item)
                    that.findChildrenData(resultArray, dataArray, item, level + 1)
                }
            }
            return resultArray
        },
        //查找子节点数据
        findChildrenData(resultArray, originArray, item, level){
            let that = this

            let deployed = 0
            let undeployed = 0
            let edit = 0
            let completed = 0

            for (let i = 0; i < originArray.length; i++) {
                let originItem = originArray[i]
                // 判断是不是item项的子项
                if (originItem.parentId === item.id) {
                    item['hasChildren'] = true
                    item['showChildren'] = false

                    originItem['level'] = level
                    originItem['visible'] = false // 子项默认隐藏
                    originItem['hiddenByCategory'] = false

                    resultArray.push(originItem)
                    that.findChildrenData(
                        resultArray,
                        originArray,
                        originItem,
                        level + 1
                    )

                    // 应该放在统计完子类数据以后
                    deployed += originItem.deployed
                    undeployed += originItem.undeployed
                    edit += originItem.edit
                    completed += originItem.completed
                }
            }
            // 计算子栏目统计合计
            item.deployed += deployed
            item.undeployed += undeployed
            item.edit += edit
            item.completed += completed
        },
        //点击展开
        onExpand(row) {
            let that = this
            let isShowChildren = !row['showChildren']
            row['showChildren'] = isShowChildren
            that.showAllSubItems(row, true, isShowChildren)
        },
        //展现全部子类数据
        showAllSubItems(item, isFirstLevlChildren, isShowChilren){
            let that = this
            let dataArray = []
            for (let i = 0; i < that.serviceList.length; i++) {
                let tempItem = that.serviceList[i]
                if (tempItem.parentId === item.id) {
                    if (isFirstLevlChildren) {
                        tempItem['visible'] = !tempItem['visible']
                    }
                    tempItem['hiddenByCategory'] = !isShowChilren

                    dataArray.push(tempItem)
                    let subItemArray = that.showAllSubItems(
                        tempItem,
                        false,
                        isShowChilren
                    )
                    dataArray = dataArray.concat(subItemArray)
                }
            }
            return dataArray
        },
        //子类数据添加类名隐藏
        rowClassNameHandler({ row, rowIndex }) {
            let className = 'pid-' + row.parentId
            if (
                row.parentId !== 0 &&
                (row['visible'] !== true || row['hiddenByCategory'] === true)
            ) {
                className += ' hiddenRow'
            }
            return className
        },
        //多选
        multiSelect(val) {
            this.allSelectedItems = val
        }
    }

}

</script>
复制代码

3.样式

<style>
    .table-con .hiddenRow {    display: none;}
</style>
复制代码

注: 样式不要写scoped!html

4.数据

数据中应有字段: 父节点id: parentId; 该节点的id: idapi