Vue動(dòng)態(tài)擴(kuò)展表頭的表格及數(shù)據(jù)方式(數(shù)組嵌套對(duì)象)
實(shí)現(xiàn)效果
需求描述
接收后端傳的json數(shù)據(jù),數(shù)據(jù)格式為數(shù)組對(duì)象嵌套數(shù)組對(duì)象再嵌套對(duì)象,需要將每個(gè)數(shù)組對(duì)象遍歷后取出想要的數(shù)據(jù),通過(guò)forEach()方法來(lái)實(shí)現(xiàn)遍歷、賦值。
數(shù)據(jù)結(jié)構(gòu)
業(yè)務(wù)代碼
<template> <div class="app-container"> <!-- 表單區(qū)域 --> <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="請(qǐng)選擇" class="treeselect-main" /> </el-form-item> <el-form-item label="品牌" prop="brandId" label-width="40px"> <el-select v-model="queryParams.brandId" filterable placeholder="請(qǐng)選擇" 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="區(qū)域" prop="areaId" label-width="80px"> <treeselect v-model="queryParams.areaId" :options="areaOptions" :normalizer="normalizer2" clearable size="small" placeholder="請(qǐng)選擇" 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="開(kāi)始日期" end-placeholder="結(jié)束日期" :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">導(dǎo)出</el-button> </el-form-item> </el-form> <!-- 表單區(qū)域結(jié)束 --> <!-- table表格區(qū)域 --> <el-table v-loading="loading" :data="mileageList" @selection-change="handleSelectionChange" border> <el-table-column label="試駕車(chē)" align="center" :show-overflow-tooltip="true"> <el-table-column label="店面" align="center" prop="storeName" :show-overflow-tooltip="true" width="180px" /> <el-table-column label="總行駛次數(shù)" 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="里程數(shù)(KM)" align="center" prop="totalMileage" width="130" :show-overflow-tooltip="true" /> <el-table-column label="總時(shí)長(zhǎng)(分鐘)" align="center" prop="totalTime" width="130" :show-overflow-tooltip="true" /> <el-table-column label="GPS預(yù)估數(shù)" 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="公務(wù)用車(chē)" align="center" :show-overflow-tooltip="true"> <!--用車(chē)數(shù)據(jù)--> <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 == '行駛次數(shù)'"> <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表格區(qū)域結(jié)束 --> <!-- 分頁(yè)區(qū)域 --> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 分頁(yè)區(qū)域結(jié)束 --> </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: [], //品牌查詢(xún) areaOptions: [], //區(qū)域 deptOptions: [], //店面 planList: [],//公務(wù)車(chē)數(shù)據(jù) dateRange: [], // 遮罩層 loading: true, // 導(dǎo)出遮罩層 exportLoading: false, // 選中數(shù)組 ids: [], // 非單個(gè)禁用 single: true, // 非多個(gè)禁用 multiple: true, // 顯示搜索條件 showSearch: false, title: "", open: false, mileageList: [], // 總條數(shù) total: 0, // 查詢(xún)參數(shù) 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: '行駛次數(shù)',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialMount, carType:this.mileageList[index].purposeTypeList[aaa].dictValue}); this.stageList.push({stageLable: '里程數(shù)(KM)',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialMileage}); this.stageList.push({stageLable: '時(shí)長(zhǎng)(分鐘)',value: this.mileageList[index].purposeTypeList[aaa].driveCarMileageSumary.officialTime}); this.stageList.push({stageLable: 'GPS預(yù)估數(shù)',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: '行駛次數(shù)',value: null,carType: null}); this.stageList.push({stageLable: '里程數(shù)(KM)',value: null}); this.stageList.push({stageLable: '時(shí)長(zhǎng)(分鐘)',value: null}); this.stageList.push({stageLable: 'GPS預(yù)估數(shù)',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; }); }, // 詳情跳轉(zhuǎn) 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(); }, /** 導(dǎo)出按鈕操作 */ handleExport() { const queryParams = this.queryParams; this.$confirm("是否導(dǎo)出里程報(bào)表數(shù)據(jù)?", "警告", { confirmButtonText: "確定", cancelButtonText: "取消", type: "warning", }) .then(() => { this.exportLoading = true; return exportMileageSumary(queryParams); }) .then((response) => { // console.log(response) this.downloads(response); this.exportLoading = false; }) }, /** * 導(dǎo)出下載 * @param {Object} response */ downloads(response) { // 拿到數(shù)據(jù)以后 通過(guò) new Blob對(duì)象 創(chuàng)建excel if (!response) { return } let time = this.getNowTime(); let fileName = time + '里程報(bào)表數(shù)據(jù).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對(duì)象 }, // 獲取當(dāng)前時(shí)間 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>
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue如何通過(guò)瀏覽器控制臺(tái)查看全局data值
在寫(xiě)vue項(xiàng)目時(shí)想到一個(gè)問(wèn)題,項(xiàng)目里面的文件都是一個(gè)個(gè)的組件,如何在控制臺(tái)中修改,查看組件data里的值呢,下面這篇文章主要給大家介紹了關(guān)于Vue如何通過(guò)瀏覽器控制臺(tái)查看全局data值的相關(guān)資料,需要的朋友可以參考下2023-04-04Vue中watch監(jiān)聽(tīng)屬性新舊值相同的問(wèn)題解決方案
這篇文章主要給大家分享了Vue中watch監(jiān)聽(tīng)屬性新舊值相同問(wèn)題解決方案,如果有遇到相同問(wèn)題的朋友,可以參考閱讀本文2023-08-08vue3?圖片懶加載的兩種方式、IntersectionObserver和useIntersectionObserve
這篇文章主要介紹了vue3?圖片懶加載的兩種方式、IntersectionObserver和useIntersectionObserver實(shí)例詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03vue3+pinia用戶(hù)信息持久緩存token的問(wèn)題解決
本文主要介紹了vue3+pinia用戶(hù)信息持久緩存token的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07解決IOS端微信H5頁(yè)面軟鍵盤(pán)彈起后頁(yè)面下方留白的問(wèn)題
微信H5項(xiàng)目,ios端出現(xiàn)了軟鍵盤(pán)輸完隱藏后頁(yè)面不會(huì)回彈,下方會(huì)有一大塊留白。這篇文章主要介紹了決微信H5頁(yè)面軟鍵盤(pán)彈起后頁(yè)面下方留白的問(wèn)題(iOS端) ,需要的朋友可以參考下2019-06-06Vue3(三)網(wǎng)站首頁(yè)布局開(kāi)發(fā)
這篇文章主要介紹了Vue3網(wǎng)站首頁(yè)布局開(kāi)發(fā),上篇文章已經(jīng)提到集成Ant Design Vue后,和Element Ui一樣,還是組件的使用,接下倆我們就來(lái)看看Vue3網(wǎng)站首頁(yè)布局開(kāi)發(fā)的相關(guān)資料,需要的朋友可以參考下面文章的具體內(nèi)容2021-10-10