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>

总结

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

相关文章

  • 基于Vue3实现鼠标滑动和滚轮控制的轮播

    基于Vue3实现鼠标滑动和滚轮控制的轮播

    在这篇文章主要为大家详细介绍了如何一步步地实现一个基于 Vue 3 的轮播组件,这个组件的特点是可以通过鼠标滑动和滚轮来控制轮播图的切换,感兴趣的可以了解下
    2024-02-02
  • 基于vue2的canvas时钟倒计时组件步骤解析

    基于vue2的canvas时钟倒计时组件步骤解析

    今天给大家介绍一款基于vue2的canvas时钟倒计时组件,这个时钟倒计时组件采用canvas动画的炫酷动画效果形式,根据剩余时间的多少变换颜色和旋转扇形的速度,适合抢购、拍卖、下注等业务场景,且对移动端友好,需要的朋友可以参考下
    2018-11-11
  • Vue 列表页带参数进详情页的操作(router-link)

    Vue 列表页带参数进详情页的操作(router-link)

    这篇文章主要介绍了Vue 列表页带参数进详情页的操作(router-link),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue 指定文字高亮的实现示例

    vue 指定文字高亮的实现示例

    在做文字处理的项目时经常会遇到搜索文字并高亮的需求,本文就来介绍vue 指定文字高亮的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • Vue Router嵌套路由(children)的用法小结

    Vue Router嵌套路由(children)的用法小结

    嵌套路由就是父路由里面嵌套他的子路由,父路由有自己的路由导航和路由容器(router-link、router-view),通过配置children可实现多层嵌套,这篇文章主要介绍了Vue--Router--嵌套路由(children)的用法,需要的朋友可以参考下
    2022-08-08
  • Vue使用openlayers实现绘制圆形和多边形

    Vue使用openlayers实现绘制圆形和多边形

    这篇文章主要为大家详细介绍了Vue如何使用openlayers实现绘制圆形和多边形,文中的示例代码讲解详细,感兴趣的小伙伴快跟随小编一起动手尝试一下
    2022-06-06
  • 使用vue-cli创建项目并webpack打包的操作方法

    使用vue-cli创建项目并webpack打包的操作方法

    本文给大家分享使用vue-cli创建项目基于webpack模板打包的配置方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-07-07
  • Vue 实现高级穿梭框 Transfer 封装过程

    Vue 实现高级穿梭框 Transfer 封装过程

    本文介绍了基于Vue2和Element-UI实现的高级穿梭框组件Transfer的设计与技术方案,组件支持多项选择,并能实时同步已选择项,包含竖版和横版设计稿,并提供了组件的使用方法和源码,此组件具备本地分页和搜索功能,适用于需要在两个列表间进行数据选择和同步的场景
    2024-09-09
  • vue中报错Duplicate keys detected:'1'. This may cause an update error的解决方法

    vue中报错Duplicate keys detected:'1'. This may c

    我们在vue开发过程中常会遇到一些错误,这篇文章主要给大家介绍了关于vue中报错Duplicate keys detected:‘1‘. This may cause an update error的解决方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • VUE登录注册页面完整代码(直接复制)

    VUE登录注册页面完整代码(直接复制)

    这篇文章主要给大家介绍了关于VUE登录注册页面的相关资料,在Vue中可以使用组件来构建登录注册页面,文中通过图文以及代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12

最新评论