Vue动态扩展表头的表格及数据方式(数组嵌套对象)

 更新时间:2023年03月27日 10:41:14   作者:半度纳  
这篇文章主要介绍了Vue动态扩展表头的表格及数据方式(数组嵌套对象),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

实现效果

需求描述

接收后端传的json数据,数据格式为数组对象嵌套数组对象再嵌套对象,需要将每个数组对象遍历后取出想要的数据,通过forEach()方法来实现遍历、赋值。

数据结构

业务代码

<template>
  <div class="app-container">
    <!-- 表单区域 -->
    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
      <el-form-item label="店面" prop="storeId" label-width="40px">
        <treeselect v-model="queryParams.storeId" :options="deptOptions" :normalizer="normalizerDept" size="small"
          placeholder="请选择" class="treeselect-main" />
      </el-form-item>
      <el-form-item label="品牌" prop="brandId" label-width="40px">
        <el-select v-model="queryParams.brandId" filterable placeholder="请选择" clearable size="medium">
          <el-option v-for="dict in brandOptions" :key="dict.id" :label="dict.brand" :value="dict.id">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="区域" prop="areaId" label-width="80px">
        <treeselect v-model="queryParams.areaId" :options="areaOptions" :normalizer="normalizer2" clearable size="small"
          placeholder="请选择" style="width:200px" />
      </el-form-item>
      <el-form-item label="日期" label-width="40px">
        <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
          range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :editable="false">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading"
          @click="handleExport">导出</el-button>
      </el-form-item>
    </el-form>
    <!-- 表单区域结束 -->
 
    <!-- table表格区域 -->
    <el-table v-loading="loading" :data="mileageList" @selection-change="handleSelectionChange" border>
	  <el-table-column label="试驾车" align="center" :show-overflow-tooltip="true">
       <el-table-column label="店面" align="center" prop="storeName" :show-overflow-tooltip="true" width="180px" />
       <el-table-column label="总行驶次数" align="center" class-name="small-padding fixed-width" width="130">
         <template slot-scope="scope">
           <el-button size="mini" type="text" @click="handleInfo(scope.row,1, scope.row.totalMount)">
             {{ scope.row.totalMount }}
           </el-button>
         </template>
       </el-table-column>
       <el-table-column label="里程数(KM)" align="center" prop="totalMileage" width="130" :show-overflow-tooltip="true" />
       <el-table-column label="总时长(分钟)" align="center" prop="totalTime" width="130" :show-overflow-tooltip="true" />
       <el-table-column label="GPS预估数" align="center" prop="predictMileage" width="130" :show-overflow-tooltip="true" />
       <el-table-column label="里程占比" align="center" prop="mileageProportion" width="130" :show-overflow-tooltip="true" />
	  </el-table-column>
			
	  <el-table-column label="公务用车" align="center" :show-overflow-tooltip="true">
		<!--用车数据-->
		<el-table-column v-for="(planItem, index) in planList" :key="index" align="center" :label="planItem.dictLabel">
		  <el-table-column v-for="(stageItem, indexChild) in planItem.stageList" :key="index+'-'+indexChild" align="center"
		    :label="stageItem.stageLable" width="100">
		    <!-- <template slot-scope="scope">
		      <span>{{ scope.row.purposeTypeList[index].stageList[indexChild].value }}</span>
		    </template> -->
			<template slot-scope="scope">
			  <span v-if="scope.row.purposeTypeList[index].stageList[indexChild].stageLable == '行驶次数'">
			     <el-button size="mini" type="text" 
							 @click="handleInfo(scope.row,2, scope.row.month,planItem.stageList[indexChild].carType)">
			       {{ scope.row.purposeTypeList[index].stageList[indexChild].value }}
			     </el-button>
			  </span>
			  <span v-else>{{ scope.row.purposeTypeList[index].stageList[indexChild].value }}</span>
			</template>
		  </el-table-column>
		</el-table-column>
	  </el-table-column>
    </el-table>
    <!-- table表格区域结束 -->
 
    <!-- 分页区域 -->
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
      @pagination="getList" />
    <!-- 分页区域结束 -->
  </div>
</template>
 
<script>
  import {
    selectMileageSumary,
    exportMileageSumary,
    exportDailyMileage
  } from "@/api/amtestdriver/drivecar";
  import Treeselect from "@riophae/vue-treeselect";
  import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  import {
    selectDept
  } from "@/api/system/dept";
  import {
    listArea,
  } from "@/api/base/area/area";
  import {
    listData
  } from "@/api/base/carBrand/carBrand";
  export default {
    name: "Mileagereport",
    components: {
      Treeselect
    },
    data() {
      return {
        brandOptions: [], //品牌查询
        areaOptions: [], //区域
        deptOptions: [], //店面
		planList: [],//公务车数据
        dateRange: [],
        // 遮罩层
        loading: true,
        // 导出遮罩层
        exportLoading: false,
        // 选中数组
        ids: [],
        // 非单个禁用
        single: true,
        // 非多个禁用
        multiple: true,
        // 显示搜索条件
        showSearch: false,
        title: "",
        open: false,
        mileageList: [],
        // 总条数
        total: 0,
        // 查询参数
        queryParams: {
          pageNum: 1,
          pageSize: 10,
          storeId: null,
          brandId: null,
          areaId: null,
        }
      };
    },
    created() {
      this.getList();
      this.listDeptByType(2);
      listData(this.queryParams).then(response => {
        this.brandOptions = response.data;
      });
      listArea().then((response) => {
        this.areaOptions = this.handleTree(response.data, "id", "parentId");
      });
    },
    methods: {
      normalizer2(node) {
        if (node.children && !node.children.length) {
          delete node.children;
        }
        return {
          id: node.id,
          label: node.name,
          children: node.children,
        };
      },
 
      //加载店面列表
      listDeptByType(type) {
        this.queryParams.type = type;
        selectDept(this.queryParams).then(response => {
          this.deptOptions = this.handleTree(response.data, "deptId");
          if (response.data.length == 1) {
            this.queryParams.storeId = response.data[0].deptId;
          }
        });
        this.queryParams.type = null;
      },
      normalizerDept(node) {
        if (node.children && !node.children.length) {
          delete node.children;
        }
        return {
          id: node.deptId,
          label: node.deptName,
          children: node.children
        };
      },
      handleSelectionChange(selection) {
        this.ids = selection.map(item => item.id)
        this.single = selection.length !== 1
        this.multiple = !selection.length
      },
      handleQuery() {
        this.queryParams.pageNum = 1;
        this.getList();
      },
      getList() {
        this.loading = true;
        if (null != this.dateRange && this.dateRange.length > 0) {
          this.queryParams.startTime = this.dateRange[0];
          this.queryParams.endTime = this.dateRange[1];
        } else {
          this.queryParams.startTime = null;
          this.queryParams.endTime = null;
        }
        selectMileageSumary(this.queryParams).then(response => {
          this.mileageList = response.rows;
		  console.log(response.rows);
		  this.mileageList.forEach((res, index) => {
		    this.mileageList[index].purposeTypeList.forEach((re, aaa) => {
		      this.stageList=[];
		      if(this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary!=null){
		        this.stageList.push({stageLable: '行驶次数',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialMount,
				carType:this.mileageList[index].purposeTypeList[aaa].dictValue});
		        this.stageList.push({stageLable: '里程数(KM)',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialMileage});
		        this.stageList.push({stageLable: '时长(分钟)',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialTime});
		        this.stageList.push({stageLable: 'GPS预估数',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialPredictMileage});
		        this.stageList.push({stageLable: '里程占比',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialMileageProportion});
		      }else{
		        this.stageList.push({stageLable: '行驶次数',value: null,carType: null});
		        this.stageList.push({stageLable: '里程数(KM)',value: null});
		        this.stageList.push({stageLable: '时长(分钟)',value: null});
		        this.stageList.push({stageLable: 'GPS预估数',value: null});
		        this.stageList.push({stageLable: '里程占比',value: null});
		      }
		      this.mileageList[index].purposeTypeList[aaa].stageList = this.stageList;
		    })
		  })
		  this.planList = (this.mileageList[0] && this.mileageList[0]['purposeTypeList']) || [];
          this.total = response.total;
          this.loading = false;
        });
      },
      // 详情跳转
      handleInfo(row, type, val, carType) {
        if (val != 0) {
          let seaParams = {};
          seaParams = this.queryParams;
          seaParams.storeId = row.storeId;
          seaParams.appType = String(type);
          seaParams.dateRange = this.dateRange;
		  seaParams.type = carType,
          this.$router.push({
            path: '/mileage-report/details',
            query: seaParams,
          })
		  // console.log("this.queryParams",this.queryParams);
        }
      },
      // 重置按钮
      resetQuery() {
        this.queryParams.startTime = []
        this.queryParams.endTime = []
        this.dateRange = [];
        this.resetForm("queryForm");
        this.handleQuery();
      },
      /** 导出按钮操作 */
      handleExport() {
        const queryParams = this.queryParams;
        this.$confirm("是否导出里程报表数据?", "警告", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          })
          .then(() => {
            this.exportLoading = true;
            return exportMileageSumary(queryParams);
          })
          .then((response) => {
            // console.log(response)
            this.downloads(response);
            this.exportLoading = false;
          })
      },
      /**
       * 导出下载
       * @param {Object} response
       */
      downloads(response) { // 拿到数据以后 通过 new Blob对象 创建excel
        if (!response) {
          return
        }
        let time = this.getNowTime();
        let fileName = time + '里程报表数据.xls'
        const blob = new Blob([response], {
          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
        })
        // const blob = new Blob(["\ufeff",response], {type: 'text/plain'});
        const href = window.URL.createObjectURL(blob)
        const downloadElement = document.createElement('a')
        downloadElement.style.display = 'none'
        downloadElement.href = href
        downloadElement.download = fileName
        document.body.appendChild(downloadElement)
        downloadElement.click()
        document.body.removeChild(downloadElement) // 下载完成移除元素
        window.URL.revokeObjectURL(href) // 释放掉blob对象
      },
      // 获取当前时间
      getNowTime() {
        var nowDate = new Date();
        var year = nowDate.getFullYear();
        var month = nowDate.getMonth() + 1 < 10 ? "0" + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
        var day = nowDate.getDate() < 10 ? "0" + nowDate.getDate() : nowDate.getDate();
        var dateStr = year + "" + month + "" + day;
        return dateStr;
      },
 
    }
  };
</script>
<style>
  .header {
    padding: 20px;
    margin-bottom: 10px;
    border-bottom: 1px solid #e6ebf5;
  }
</style>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue如何通过浏览器控制台查看全局data值

    Vue如何通过浏览器控制台查看全局data值

    在写vue项目时想到一个问题,项目里面的文件都是一个个的组件,如何在控制台中修改,查看组件data里的值呢,下面这篇文章主要给大家介绍了关于Vue如何通过浏览器控制台查看全局data值的相关资料,需要的朋友可以参考下
    2023-04-04
  • Vue中watch监听属性新旧值相同的问题解决方案

    Vue中watch监听属性新旧值相同的问题解决方案

    这篇文章主要给大家分享了Vue中watch监听属性新旧值相同问题解决方案,如果有遇到相同问题的朋友,可以参考阅读本文
    2023-08-08
  • vue3 图片懒加载的两种方式、IntersectionObserver和useIntersectionObserver实例详解

    vue3 图片懒加载的两种方式、IntersectionObserver和useIntersectionObserve

    这篇文章主要介绍了vue3 图片懒加载的两种方式、IntersectionObserver和useIntersectionObserver实例详解,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • 一起来看看Vue的核心原理剖析

    一起来看看Vue的核心原理剖析

    这篇文章主要为大家详细介绍了Vue的核心原理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • vue中自定义组件双向绑定的三种方法总结

    vue中自定义组件双向绑定的三种方法总结

    这篇文章主要介绍了vue中自定义组件双向绑定的三种方法总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • vue3+pinia用户信息持久缓存token的问题解决

    vue3+pinia用户信息持久缓存token的问题解决

    本文主要介绍了vue3+pinia用户信息持久缓存token的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Vue3.0的优化总结

    Vue3.0的优化总结

    在本篇文章里小编给大家整理的是一篇关于Vue3.0的优化总结内容,有需要的朋友们可以学习下。
    2020-10-10
  • 解决IOS端微信H5页面软键盘弹起后页面下方留白的问题

    解决IOS端微信H5页面软键盘弹起后页面下方留白的问题

    微信H5项目,ios端出现了软键盘输完隐藏后页面不会回弹,下方会有一大块留白。这篇文章主要介绍了决微信H5页面软键盘弹起后页面下方留白的问题(iOS端) ,需要的朋友可以参考下
    2019-06-06
  • Vue3(三)网站首页布局开发

    Vue3(三)网站首页布局开发

    这篇文章主要介绍了Vue3网站首页布局开发,上篇文章已经提到集成Ant Design Vue后,和Element Ui一样,还是组件的使用,接下俩我们就来看看Vue3网站首页布局开发的相关资料,需要的朋友可以参考下面文章的具体内容
    2021-10-10
  • 浅谈Vuex的状态管理(全家桶)

    浅谈Vuex的状态管理(全家桶)

    本篇文章主要介绍了浅谈Vuex状态管理(全家桶),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11

最新评论