vue使用Element的el-table实现表格嵌套及表格内容的折叠效果

开发背景

由于开发页面的内容较多,包含两三个表格,这样展示效果有点不乐观,因此其中一个表格的内容采用表格嵌套及表格内容折叠的方式来呈现。

实现思路

  1. 表格嵌套
  2. 表格内容折叠
  3. 点击表格【人工成本】月份下内容区的金额与天数互换

实现过程

最开始拿到原型的时候,看了Element的官网的el-table的嵌套和折叠效果,发现并不适用我的这个场景。

  • 表格嵌套
    官网是采用了在el-table的el-table-column中再次嵌套el-table-column的方式实现的。由于我的需求是,嵌套了表格,但是该行的后半部分没有内容,所以,我采用通过构造数据结构,然后进行单元格的合并的方式来呈现表格嵌套的效果。
    1. 通过handleDetailData方法将数据进行处理。将表格的内容分为【人工成本、其它福利补贴、其它成本、合计行】这四块。并分别设置这四块内容的tableType来代表它属于哪个区块。然后将这四块数据进行整合,到表格。
    2. 通过arraySpanMethod方法对表格单元格合并,具体合并规则见element官网el-talbe的span-method的实现方式
    3. 通过tableCellClassName方法对特殊单元格样式进行修改
    4. 这里要注意的是,当鼠标滑过表格的内容行的时候,该行的样式会发生变化,如背景色。这里,我要保证其它成本的表格头,在鼠标滑到该行时,样式不能发生变化。这时就需要修改鼠标滑过的样式
    .other-header {
       background: #6c81cd;
       color: #fff;
    }
    
    //由于表格自带鼠标滑过表格体时,该行背景色会变化,所以,设置它的hover样式与它原来的样式保持一致
    tbody tr:hover>td {
       background-color: unset !important;
    }
    
    tbody tr:hover {
       .other-header {
           background: #6c81cd !important;
           color: #fff !important;
       }
       .tatalRow-cursor{
           background: #322323;
           cursor: pointer;
       }
    }
    

在这里插入图片描述

  • 表格折叠
    这里并没有采用elment中el-table的折叠方法,不适用,它折叠的内容是父子关系。而我是同级关系。确切的说,我这里是对内容区的展示或影藏。
    1. 通过tableRowClassName方法来修改某一行的样式。通过设置要折叠的行的样式display:none来隐藏
    2. 通过onTableCellClick方法来做点击折叠,收起的效果。主要是对变量expand的值的修改
  • 点击表格【人工成本】月份下内容区的金额与天数互换
    1. 通过onTableCellClick方法来做点击金额,与天数 做切换

源代码

<template>
    <div class="budget_income_info">
        <el-table :data="tableData" style="width: 100%" size="mini" border
            show-overflow-tooltip
            :header-cell-style="{ background: '#6c81cd', color: '#fff' }" 
            :span-method="arraySpanMethod" 
            :cell-class-name="tableCellClassName" 
            :row-class-name="tableRowClassName"
            @cell-click="onTableCellClick"
            >
            <el-table-column label="岗位条目" align="center">
                <el-table-column label="岗位名称" prop="posiName" min-width="70">
                    <template slot-scope="scope">
                        {{ scope.row.posiName }}
                        <span v-if="!expand && scope.row.tableType === 'tatalRow'" style="color: #aaa;">(点击查看更多详情)</span>
                        <span v-if="expand && scope.row.tableType === 'tatalRow'" style="color: #aaa;">(点击收起)</span>
                        <i :class="!expand ? 'el-icon-caret-bottom' : 'el-icon-caret-top'"
                            v-if="scope.row.tableType === 'tatalRow'"></i>
                    </template>
                </el-table-column>
                <el-table-column label="职系" prop="posiGradeType" min-width="70"></el-table-column>
                <el-table-column label="月付费额" prop="monthlyPayAmount" min-width="60"></el-table-column>
                <el-table-column label="数量" prop="posiCount" min-width="35"></el-table-column>
                <el-table-column label="语言" prop="langName" min-width="40"></el-table-column>
                <el-table-column label="级别" prop="posiRank" min-width="40"></el-table-column>
                <el-table-column label="业务类型" prop="positionName" min-width="75"></el-table-column>
                <el-table-column label="等级" prop="posiLevel" min-width="40"></el-table-column>
                <el-table-column label="地城" prop="cityName" min-width="60"></el-table-column>
                <el-table-column label="人天成本" prop="budgetCostAmount" min-width="65"></el-table-column>
            </el-table-column>
            <el-table-column v-for="(item, index) in allYearMonth" :label="item" align="center" :key="item" min-width="60"
            >
                <template slot-scope="scope" v-show="scope.row.budgetValues && scope.row.budgetdays">
                    {{ 
                        isValToDays && scope.row.tableType === 'laborCost' ?
                            scope.row.budgetdays && scope.row.budgetdays[index] && scope.row.budgetdays[index] :
                            scope.row.budgetValues && scope.row.budgetValues[index] && ThousandFormat(scope.row.budgetValues[index])
                    }}
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>
<script>
import { queryQuotaType } from '@/api/api';
export default {
    props: {
        detailData: {
            type: Object,
            default: function () {
                return {};
            }
        },
        allYearMonth: {
            type: Array,
            default: function () {
                return [];
            }
        }
    },
    data() {
        return {
            tableData: [],
            detailDataObj: {},
            expand: false, //展开:false
            isValToDays:false, //是否由金额转天
            detailCodesObj:{},
        }
    },
    mounted() {
        this.queryQuotaType();
        this.detailDataObj = this.detailData;
    },
    methods: {
        //某个单元格的样式
        tableCellClassName({ row, rowIndex, column, columnIndex }) {
            if (row.tableType == 'otherHeader' && (columnIndex === 0 || columnIndex === 5)) {
                return 'other-header';
            }
            if (row.tableType === 'tatalRow' && (columnIndex === 0)){
                return 'tatalRow-cursor'
            }
            return '';
        },
        //查看预算填报类型
        queryQuotaType() {
            let params = {
                quotaType: 'cost', //预算收入 income,  预算成本 cost
            }
            queryQuotaType(params).then(res => {
                if (res.success) {
                    this.detailCodesObj = res.entity;
                    this.handleDetailData();
                }
            })
        },
        //处理详情数据
        handleDetailData() {
            let { costList, otherList, totals } = this.detailDataObj;

            //人工成本
            costList.forEach(item => {
                if (item.detailCode === this.detailCodesObj.otherCode) { //其它福利补贴
                    item.tableType = 'otherWelfareSubsidies';
                    item.posiName = '其它福利补贴'
                }else{
                    item.tableType = 'laborCost';
                }
            })

            //其它成本
            let temp = {};
            if (otherList.length > 0) {
                temp.tableType = 'otherHeader';
                temp.budgetValues = new Array(this.allYearMonth.length).fill('');
                temp.posiName = '预算条目大类';
                temp.posiRank = '预算条目小类';
                otherList.forEach(item => {
                    item.tableType = 'other';
                    item.posiName = item.expenseTypeOneDesc;
                    item.posiRank = item.expenseTypeTwoDesc;
                })
            }

            //合计行
            let totalRow = {
                tableType: 'tatalRow',
                posiName: '成本合计',
                budgetValues: totals
            }
            
            if(Object.keys(temp).length > 0){
                this.tableData = [...costList, temp, ...otherList, totalRow];
            }else{
                this.tableData = [...costList, ...otherList, totalRow];
            }
            
        },
        //合并单元格
        arraySpanMethod({ row, column, rowIndex, columnIndex }) {
            //其它福利补贴
            if (row.detailCode === this.detailCodesObj.otherCode) {
                if (columnIndex === 0) {
                    return [1, 10]
                } else if (columnIndex >= 1 && columnIndex <= 9) {
                    return [0, 0]
                }
            }
            // 其它成本表头
            if (row.tableType === 'otherHeader') {
                if (columnIndex === 0) {
                    return [1, 5];
                } else if (columnIndex === 5) {
                    return [1, 5];
                } else if (columnIndex === 10) {
                    return [1, this.allYearMonth.length];
                } else if ((columnIndex >= 1 && columnIndex <= 4) || (columnIndex >= 6 && columnIndex <= 9) || columnIndex > 10) {
                    return [0, 0]
                }
            }
            //其它成本表体
            if (row.tableType === 'other') {
                if (columnIndex === 0) {
                    return [1, 5];
                } else if (columnIndex === 5) {
                    return [1, 5];
                } else if ((columnIndex >= 1 && columnIndex <= 4) || (columnIndex >= 6 && columnIndex <= 9)) {
                    return [0, 0]
                }
            }
            //合计行
            if (row.tableType === 'tatalRow') {
                if (columnIndex === 0) {
                    return [1, 10]
                } else if (columnIndex >= 1 && columnIndex <= 9) {
                    return [0, 0]
                }
            }
        },
        //某一行的样式
        tableRowClassName({ row, rowIndex }) {
            //折叠展开 隐藏表格内容,只展示最后一行
            if (rowIndex !== this.tableData.length - 1 && !this.expand) {
                return 'row-none'
            }
            // if(this.expand && rowIndex !== this.tableData.length - 1){
            //     return 'row-block'
            // }
            //成本合计行,文字加粗
            if (rowIndex === this.tableData.length - 1) {
                return 'font-weigth'
            }
        },
        //单击某个单元格
        onTableCellClick(row, column, cell, event) {
            //点击成本合计行,折叠、展开表体内容
            if (row.tableType === 'tatalRow' && column.property === 'posiName') {
                this.expand = !this.expand; //折叠 、展开
            }

            //点击金额,与天数 做切换
            if(row.tableType === 'laborCost' && this.allYearMonth.includes(column.label)){
                this.isValToDays = !this.isValToDays;
            }
        }
    }
}
</script>
<style lang="less" scoped>
.budget_income_info {
    margin: 10px 0px;

    /deep/ .el-table {
        .cell {
            padding: 0px 0px !important;
            border: none;
            text-align: center !important;
        }

        .other-header {
            background: #6c81cd;
            color: #fff;
        }
		//由于表格自带鼠标滑过表格体时,该行背景色会变化,所以,设置它的hover样式与它原来的样式保持一致
        tbody tr:hover>td {
            background-color: unset !important;
        }

        tbody tr:hover {
            .other-header {
                background: #6c81cd !important;
                color: #fff !important;
            }
            .tatalRow-cursor{
                background: #322323;
                cursor: pointer;
            }
        }

        .row-none {
            display: none;
            // position: absolute;
            // top: 0;
            // left: 0;
            // opacity: 0;
            // z-index: 0;
            // visibility: hidden;
            // transition: all ease-in .5s;
        }
        // .row-block{
        //     opacity: 1;
        //     visibility: visible;
        //     z-index: 999;
        // }

        .font-weigth {
            font-weight: bold;

            i {
                font-size: 16px;
                font-weight: bold;
            }
        }
    }
}
</style>

主要数据

处理后要渲染的数据如下:

[
    {
        "id": null,
        "applicationId": "xg20cd30d843bac4c208da92c041285c6ad",
        "detailCode": "1201",
        "budgetDate": null,
        "budgetValues": [33609,43494,43494,43494,43494,43494,43494,43494,43494,43494,43494,43494,11862],
        "itemType": null,
        "expenseTypeOneCode": null,
        "expenseTypeTwoCode": null,
        "beginDate": null,
        "endDate": null,
        "quotaType": "cost",
        "budgetValue": null,
        "itemTypeName": null,
        "item": null,
        "note": null,
        "rowIndex": 1,
        "total": 523905,
        "posiName": "测试岗位",
        "posiGradeType": "技术职系",
        "monthlyPayAmount": "10000.00",
        "posiCount": "3.00",
        "langName": "中文",
        "posiRank": "高级",
        "positionName": "数据分析",
        "posiLevel": "I",
        "cityName": "北京1",
        "budgetCostAmount": "659.00",
        "expenseTypeOneDesc": null,
        "expenseTypeTwoDesc": null,
        "budgetdays": [17, 22,22,22,22,22,22, 22,22,22,22,22, 6],
        "tableType": "laborCost"
    },
    {
        "id": null,
        "applicationId": "xg20cd30d843bac4c208da92c041285c6ad",
        "detailCode": "1201",
        "budgetDate": null,
        "budgetValues": [22406,28996,28996,28996,28996,28996,28996,28996,28996,28996,28996,28996,7908],
        "itemType": null,
        "expenseTypeOneCode": null,
        "expenseTypeTwoCode": null,
        "beginDate": null,
        "endDate": null,
        "quotaType": "cost",
        "budgetValue": null,
        "itemTypeName": null,
        "item": null,
        "note": null,
        "rowIndex": 2,
        "total": 349270,
        "posiName": "岗位2",
        "posiGradeType": "技术职系",
        "monthlyPayAmount": "10000.00",
        "posiCount": "2.00",
        "langName": "中文",
        "posiRank": "高级",
        "positionName": "数据分析",
        "posiLevel": "I",
        "cityName": "北京1",
        "budgetCostAmount": "659.00",
        "expenseTypeOneDesc": null,
        "expenseTypeTwoDesc": null,
        "budgetdays": [17,22,22,22,22,22,22,22,22,22,22,22,6],
        "tableType": "laborCost"
    },
    {
        "id": null,
        "applicationId": "xg20cd30d843bac4c208da92c041285c6ad",
        "detailCode": "1202",
        "budgetDate": null,
        "budgetValues": [23,34,23,0,0,0,0,0,0,0,0,0,0],
        "itemType": null,
        "expenseTypeOneCode": null,
        "expenseTypeTwoCode": null,
        "beginDate": null,
        "endDate": null,
        "quotaType": "cost",
        "budgetValue": null,
        "itemTypeName": null,
        "item": null,
        "note": null,
        "rowIndex": 3,
        "total": null,
        "posiName": "其它福利补贴",
        "posiGradeType": null,
        "monthlyPayAmount": null,
        "posiCount": null,
        "langName": null,
        "posiRank": null,
        "positionName": null,
        "posiLevel": null,
        "cityName": null,
        "budgetCostAmount": null,
        "expenseTypeOneDesc": null,
        "expenseTypeTwoDesc": null,
        "budgetdays": null,
        "tableType": "otherWelfareSubsidies"
    },
    {
        "tableType": "otherHeader",
        "budgetValues": ["","","","","","","","","","","","",""],
        "posiName": "预算条目大类",
        "posiRank": "预算条目小类"
    },
    {
        "id": null,
        "applicationId": "xg20cd30d843bac4c208da92c041285c6ad",
        "detailCode": "0101",
        "budgetDate": null,
        "budgetValues": [23, 34,23,12, 43, 0, 0, 0,0, 0, 0,0,0],
        "itemType": null,
        "expenseTypeOneCode": null,
        "expenseTypeTwoCode": null,
        "beginDate": null,
        "endDate": null,
        "quotaType": "other",
        "budgetValue": null,
        "itemTypeName": null,
        "item": null,
        "note": null,
        "rowIndex": 1,
        "total": 135,
        "posiName": "交通费/差旅费",
        "posiGradeType": null,
        "monthlyPayAmount": null,
        "posiCount": null,
        "langName": null,
        "posiRank": "市内交通费",
        "positionName": null,
        "posiLevel": null,
        "cityName": null,
        "budgetCostAmount": null,
        "expenseTypeOneDesc": "交通费/差旅费",
        "expenseTypeTwoDesc": "市内交通费",
        "budgetdays": null,
        "tableType": "other"
    },
    {
        "id": null,
        "applicationId": "xg20cd30d843bac4c208da92c041285c6ad",
        "detailCode": "2001",
        "budgetDate": null,
        "budgetValues": [45,23,45,12,12,0, 0,0,0,0,0,0, 0],
        "itemType": null,
        "expenseTypeOneCode": null,
        "expenseTypeTwoCode": null,
        "beginDate": null,
        "endDate": null,
        "quotaType": "other",
        "budgetValue": null,
        "itemTypeName": null,
        "item": null,
        "note": null,
        "rowIndex": 2,
        "total": 137,
        "posiName": "内部支出",
        "posiGradeType": null,
        "monthlyPayAmount": null,
        "posiCount": null,
        "langName": null,
        "posiRank": "其他成本",
        "positionName": null,
        "posiLevel": null,
        "cityName": null,
        "budgetCostAmount": null,
        "expenseTypeOneDesc": "内部支出",
        "expenseTypeTwoDesc": "其他成本",
        "budgetdays": null,
        "tableType": "other"
    },
    {
        "tableType": "tatalRow",
        "posiName": "成本合计",
        "budgetValues": [56106,72581,72581, 72514,72545, 72490,72490, 72490, 72490,72490,72490,72490, 19770]
    }
]

效果图

  • 收起效果
    在这里插入图片描述
  • 展开效果
    在这里插入图片描述
  • 点击这块内容区任何一处将所有金额和天数进行交替展示
    在这里插入图片描述
  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现 `el-table` 表格和 `el-input` 的搜索功能,可以借助 `computed` 计算属性和 `watch` 监听器来实现。 首先,在 `el-table` 中添加一个 `el-input` 组件,用于输入搜索关键字,如下所示: ```html <template> <div> <el-input v-model="searchText" placeholder="请输入搜索关键字"></el-input> <el-table :data="filteredData" :columns="columns"> </el-table> </div> </template> ``` 然后,在 `data` 中定义 `searchText` 和 `tableData`,分别表示搜索关键字和表格数据,如下所示: ```javascript data() { return { searchText: '', tableData: [ { name: '张三', age: 18, address: '北京市海淀区' }, { name: '李四', age: 20, address: '上海市浦东新区' }, { name: '王五', age: 22, address: '广州市天河区' }, { name: '赵六', age: 24, address: '深圳市南山区' } ], columns: [ { prop: 'name', label: '姓名' }, { prop: 'age', label: '年龄' }, { prop: 'address', label: '地址' } ] } } ``` 接着,在 `computed` 中定义 `filteredData` 计算属性,用于过滤数据,如下所示: ```javascript computed: { filteredData() { const searchText = this.searchText.trim().toLowerCase(); if (searchText) { return this.tableData.filter((row) => { return Object.keys(row).some((key) => { return String(row[key]).toLowerCase().indexOf(searchText) > -1; }); }); } else { return this.tableData; } } } ``` 在 `filteredData` 计算属性中,使用 `trim` 方法去除搜索关键字的前后空格,使用 `toLowerCase` 方法将搜索关键字转换为小写字母,然后使用 `filter` 方法过滤表格数据,使用 `Object.keys` 方法获取每一行数据的所有属性名,使用 `some` 方法判断每一行数据的属性值是否包含搜索关键字,如果包含则返回 `true`,否则返回 `false`。 最后,在 `watch` 中监听 `searchText` 的变化,实时更新过滤后的数据,如下所示: ```javascript watch: { searchText() { this.$nextTick(() => { this.$refs.table.doLayout(); }); } } ``` 在 `watch` 中,使用 `$nextTick` 方法等待 DOM 更新后,再调用 `doLayout` 方法实时更新过滤后的数据。 通过以上步骤,即可实现 `el-table` 表格和 `el-input` 的搜索功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值