zoukankan      html  css  js  c++  java
  • vue 表格内容异步导出

    在做表格导出的时候,之前的框架一贯的做法是,导出拿到页面中缓存的查询条件,将条件参数在拼接,通过window.loaction的方式将参数拼接给后台,在打开,

    // 导出
    handleExport() {
        if(this.total > this.exportLimit){
            this.$_c.msg('导出数据个数不能大于'+this.exportLimit,{type:'warning'})
            return
        }
        if(this.url.export){
            this.handleFieldsChangeBefore && this.handleFieldsChangeBefore()
            this.exportParams = this.$lockr.get('exportParams') || this.searchFields
    
            if(!this.exportParams.hasOwnProperty(this.exportTime[0]) || !this.exportParams.hasOwnProperty(this.exportTime[1])){//如果没传时间则默认查最近7天
                if(!this.exportParams[this.exportTime[0]] || !this.exportParams[this.exportTime[1]]){
                    let now = new Date().getTime()
                    this.exportParams[this.exportTime[0]] = now - 7*24*3600*1000
                    this.exportParams[this.exportTime[1]] = now
                }
            }
            this.initExportParams && this.initExportParams()
            this.downloadFileByUrl(this.url.export,this.exportParams,this.exportFileName)
        }
    },
    /**
     * 通过Url下载文件
     * @param {String} url 下载路径
     * @param {Object} params 参数
     * @param {String} fileName 文件名
     */
    export function downloadFileByUrl(url,params={},fileName="file") {
      url = process.env.VUE_APP_URL2 + url 
      const keys = Object.keys(params)
      for(let i=0; i<keys.length; i++) {
        url = url + (i === 0 ? '?' : '&') + keys[i] + '=' + params[keys[i]]
      }
      url += (keys.length > 0 ? '&' : '?') + 'access_token=' + cookies.get('access_token')
      if (fileName) {
        var a = document.createElement('a');
        // safari doesn't support this yet
        if (typeof a.download === 'undefined') {
            window.location = url
        } else {
            a.href = url;
            a.download = fileName;
            document.body.appendChild(a);
            a.click();
            a.remove();
        }
      } else {
        window.location = url;
      }
    }
    View Code

    但是在实际过程会有一个问题,就是数据量特别大的时候,就会等待很长的时间,才跳转,如果这个时候一直点击导出,可能导致系统崩溃问题

    解决办法:

    异步导出,通过接口向后台发送查询参数,后台在返回一个标识,前段通过拿到的这个标识,进行轮询,如果获取到了路径,就打开并且关闭定时器

    handleExport(val) {
        if(this.total > this.exportLimit){
            this.$_c.msg('导出数据个数不能大于'+this.exportLimit,{type:'warning'})
            return
        }
        if (this.loadExcelTimer != null) {
            window.clearInterval(this.loadExcelTimer)
            this.loadExcelTimer = null
        }
        this.$loading.showLoading({text:'导出中……'})
        this.$ajax.post(this.url.export, this.exportParams).then(res => {
            if (res.code == 200) {
                this.loadExcelTimer = setInterval(() => {
                    this.getAsyncExcel(res)
                }, 2000)
            }
        }).catch(err => {
            this.restInterval()
            this.$message.error('导出失败');
        })
    },
    
    getAsyncExcel(result) {
        console.log('export table...')
        if (!result.data) return false
        this.$ajax.get(this.url.download, { id: result.data }).then(res => {
            if (res.data != null) {
                this.restInterval()
                //可以去下载了
                let url = process.env.VUE_APP_URL2 + preUrl.files + res.data //创建下载链接
                let link = document.createElement('a') //创建a标签
                link.style.display = 'none'  //将a标签隐藏
                link.href = url  //给a标签添加下载链接
                link.setAttribute('download', '文件') //此处注意,要给a标签添加一个download属性,属性值就是文件名称,否则下载出来的文件是没有属性的,空白白
                document.body.appendChild(link)
                link.click()  //执行a标签
            }
        })
    },

    完整的vue

    <template>
        <TBLayout>
            <!-- search-form -->
            <content-box :slot="searchFormInfos.slot" :options="{'100%',padding:'20px 20px 0 20px'}">
                <self-form :formInfos="searchFormInfos" :fields="searchFields" @setFields="changeFields" @button-click="handleButtonClick" />
            </content-box>
            <btns-group slot="btnsgroup" :data="batchButtons" @button-click="handleButtonClick" v-if="isShowTable" />
            <!-- table -->
            <self-table :slot="tableInfos.slot" v-if="isShowTable" :tableData="tableData" :tableInfos="tableInfos" :status="originBaseData" @selection-change="handleSelectionChange" @button-click="handleButtonClick" />
            <!--  pager -->
            <self-pager slot="pager" @button-click="handleButtonClick" v-if="isShowTable">
                <el-pagination :current-page="pageNum" :page-sizes="pageSizes" :page-size="pageSize" :layout="layout" :total="total" slot="pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange">
                </el-pagination>
            </self-pager>
            <div slot="otherPager" class="chart-page" style="" v-if="!isShowTable">
                <div class="echarts" ref="chart"></div>
            </div>
        </TBLayout>
    </template>
    <script>
    import echarts from 'echarts'
    import Crud from '@frameworks/assets/js/Crud'
    import TBLayout from '@modules/baselayout/views/TBLayout'
    import { searchFormInfos, batchButtons, tableInfos } from './PointHistory'
    import { preUrl } from '@frameworks/conf/api'
    import Api from '@frameworks/conf/api'
    import { formatDate } from '@frameworks/assets/js/Filters'
    export default {
        mixins: [Crud],
        components: { TBLayout },
        data() {
            return {
                url: {
                    getData: Api.getPageByTime,
                    export: Api.exportHistory,
                    download: Api.downLoadExcel
                },
                detailParams: {
                    url: '',
                    params: {}
                },
                methodGet: 'post',
                batchButtons,
                searchFormInfos: searchFormInfos,
                tableInfos: tableInfos,
                isShowTable: true,//是否展示表格
                checkNodes: [],//树选中的节点
                chart: null,
                resizeTimer: null,
                chartOption: {
                    title: {
                        text: '趋势图'
                    },
                    tooltip: {
                        trigger: 'axis',
                        appendToBody: true,
                        formatter: (params) => {
                            let format = "yyyy-MM-dd HH:mm:ss"
                            let str = ""
                            for (let i = 0; i < params.length; i++) {
                                let p = params[i]
                                let node = this.checkNodes[p.seriesIndex]
                                let date = new Date(p.name)
                                str +=
                                    '<tr><td style="color:' +
                                    p.color +
                                    '">' +
                                    p.marker +
                                    "</td><td>" +
                                    p.seriesName +
                                    ":</td><td>" +
                                    p.value[1] +
                                    (p.data.unit || '') +
                                    "</td></tr>";
                            }
                            str =
                                "<p>" +
                                formatDate(params[0].data.name, format) +
                                "</p><table>" +
                                str +
                                "</table>";
                            return str
                        },
                        axisPointer: {
                            animation: false
                        }
                    },
                    xAxis: {
                        type: 'time',
                        splitLine: {
                            show: false
                        }
                    },
                    yAxis: {
                        name: '',
                        type: 'value',
                        boundaryGap: [0, '100%'],
                        splitLine: {
                            show: false
                        }
                    },
                    color: ['rgb(0, 137, 249)', 'rgb(0, 201, 134)', 'rgb(255, 132, 31)', 'rgb(216, 86, 207)', 'rgb(252, 206, 8)', 'rgb(133, 172, 193)'],
                    series: [{
                        name: '模拟数据',
                        type: 'line',
                        showSymbol: false,
                        hoverAnimation: false,
                        data: []
                    }]
                },
                exportLimit: 1000000,
                unit: '',
                loadExcelTimer: null
            }
        },
        methods: {
            async handleSearchBefore() {
                let now = new Date().getTime()
                this.searchFields.startTime = now - 7 * 24 * 3600 * 1000
                this.searchFields.endTime = now
                this.searchFormInfos.children[3].options.defaultValue = ''
                this.searchFields.tagNames = ''
                return await false
            },
    
            handleFieldsChangeBefore() {
                delete this.searchFields.checkd
                delete this.searchFields.data
                delete this.searchFields.initDefault
            },
    
            handleFieldsChangeAfter(val) {
                if (val.field.pointType) {
                    this.searchFormInfos.children[3].options.pointType = val.field.pointType
                    this.searchFields.tagNames = ''
                } else if (val.field.tagNames) {
                    this.searchFormInfos.children[3].options.defaultValue = val.field.tagNames
                    this.checkNodes = val.field.checkNodes || []
                }
    
            },
    
            //
            handleSearch(showMsg = false) {
                if (this.searchFields.showTypeData == 1) {
                    this.isShowTable = true
                } else if (this.searchFields.showTypeData == 2) {
                    this.isShowTable = false
                }
                if (!this.isShowTable) {
                    this.$loading.showLoading()
                    if (this.checkNodes && this.checkNodes.length > 10) {
                        this.$_c.msg('曲线查看选择的测点不能超过10个,请重新选择', { type: 'warning' })
                        this.$loading.hideLoading()
                        return false
                    }
                }
                this.handleFieldsChangeBefore && this.handleFieldsChangeBefore()
                //如果是曲线是查所有的数据,表格的是需要进行分页的
                let data = this.isShowTable ? Object.assign({
                    pageNum: this.startNum == 0 ? this.pageNum : this.startNum,
                    pageSize: this.pageSize,
                }, this.searchFields) : this.searchFields
                //统一删除showTypeData字段
                //delete data.showTypeData
                delete this.searchFields.checkNodes
                //获取数据
                this.$ajax.asyncAjax(this.url.getData, data, this.methodGet).then((res) => {
                    if (res.code == 200) {
                        //如果是表格
                        if (this.isShowTable) {
                            this.startNum = 0
                            this.tableData = []
                            this.total = res.data.total ? res.data.total : 0
                            this.pageNum = res.data.pageNum ? res.data.pageNum : 1
                            this.pageCount = res.data.pages ? res.data.pages : 0
                            let result = this.isPager ? res.data[this.dataListField] : res.data
                            if (result.length == 0 && this.pageNum != 1) {//如果最后一页已经没有数据,那就查前一页
                                if (this.searchForwardCount < 1) {
                                    this.pageNum -= 1;
                                    this.searchForwardCount += 1;
                                } else {
                                    this.pageNum = 1;
                                }
                                this.handleSearch();
                                return
                            }
                            this.tableData = this.parseSearchResult(result)
                            //如果需要,把数据返回给父类
                            this.$emit('dto-data', res)
                            //缓存查询条件
                            this.isSearchParamsToLocalStorage && this.setSearchFieldStorage()
                            //获取数据后对数据进行修饰
                            this.handleSearchSuccess && this.handleSearchSuccess(res, showMsg)
                        } else {//曲线
                            this.initChart()
                            this.initData(res)
                        }
                    } else {
                        this.tableData = []
                        this.handleSearchFailed && this.handleSearchFailed(res)
                    }
                    this.searchForwardCount = 0;
                }).catch(res => {
                    this.$loading.hideLoading()
                    this.searchForwardCount = 0;
                    this.tableData = []
                    this.handleSearchError && this.handleSearchError(res)
                })
                if (this.clearSelection) this.handleSelectionChange()
            },
    
            initChart() {
                this.chart = echarts.init(this.$refs.chart)
                this.chart.clear()
                this.chart.setOption(this.chartOption)
                this.chart.resize()
            },
    
            handleExport(val) {
                if(this.total > this.exportLimit){
                    this.$_c.msg('导出数据个数不能大于'+this.exportLimit,{type:'warning'})
                    return
                }
                if (this.loadExcelTimer != null) {
                    window.clearInterval(this.loadExcelTimer)
                    this.loadExcelTimer = null
                }
                this.$loading.showLoading({text:'导出中……'})
                // this.exportParams = {
                //     startTime: 1607909692028,
                //     endTime: 1608514492028,
                //     pointType: 1,
                //     tagNames: 'M0101.BL.ITCWSD_LTD_1,M0101.BL.ITCWSD_LTD_1.1.itEnvCCDownHum,M0101.BL.ITCWSD_LTD_1.1.itEnvCCDownTemp,M0101.BL.ITCWSD_LTD_1.1.itEnvCCIndex,M0101.BL.ITCWSD_LTD_1.1.itEnvCCUpHum',
                //     showTypeData: 1,
                //     rowNum: -1,
                //     activeField: 'pointType',
                //     timeZone: -8,
                //     pageNum: 1,
                //     pageSize: 10
                // }
                this.$ajax.post(this.url.export, this.exportParams).then(res => {
                    if (res.code == 200) {
                        this.loadExcelTimer = setInterval(() => {
                            this.getAsyncExcel(res)
                        }, 2000)
                    }
                }).catch(err => {
                    this.restInterval()
                    this.$message.error('导出失败');
                })
            },
    
            getAsyncExcel(result) {
                console.log('export table...')
                if (!result.data) return false
                this.$ajax.get(this.url.download, { id: result.data }).then(res => {
                    if (res.data != null) {
                        this.restInterval()
                        //可以去下载了
                        let url = process.env.VUE_APP_URL2 + preUrl.files + res.data //创建下载链接
                        let link = document.createElement('a') //创建a标签
                        link.style.display = 'none'  //将a标签隐藏
                        link.href = url  //给a标签添加下载链接
                        link.setAttribute('download', '文件') //此处注意,要给a标签添加一个download属性,属性值就是文件名称,否则下载出来的文件是没有属性的,空白白
                        document.body.appendChild(link)
                        link.click()  //执行a标签
                    }
                })
            },
    
            initData(result) {
                let rowData = result.data && result.data.list
                this.unit = rowData[0].unitName
                let legendArr = [], series = []
                for (let item of this.checkNodes) {
                    legendArr.push(item.name)
                }
                //首先遍历一遍进行分组
                for (let i = 0; i < this.checkNodes.length; i++) {
                    let row = this.checkNodes[i]
                    series.push(
                        {
                            name: legendArr[i] || row.id,
                            type: 'line',
                            showSymbol: false,
                            hoverAnimation: false,
                            data: this.getDataByCode(row, rowData)
                        }
                    )
                }
                this.$loading.hideLoading()
                this.chart.setOption({
                    legend: {
                        data: legendArr
                    },
                    series
                })
                this.chart.resize()
            },
    
            //数据处理
            getDataByCode(rowObj, rowData) {
                let dataArr = []
                for (let i = 0; i < rowData.length; i++) {
                    let row = rowData[i]
                    let _arr = []
                    _arr.push(formatDate(row.time, 'yyyy-MM-dd HH:mm:ss'))
                    _arr.push(row.value)
                    rowObj.id == row.tagName && dataArr.push({
                        name: new Date(row.time),
                        value: _arr,
                        unit: row.unitName
                    })
                }
                return dataArr
            },
    
            init() {
                window.onresize = () => {
                    return (() => {
                        if (this.resizeTimer) { clearTimeout(this.resizeTimer) }
                        this.resizeTimer = setTimeout(() => {
                            if (this.chart) {
                                this.chart.resize();
                            }
                        }, 300)
                    })()
                }
            },
    
            restInterval() {
                this.$loading.hideLoading()
                window.clearInterval(this.loadExcelTimer)
                this.loadExcelTimer = null
            }
        },
        mounted() {
            this.init()
        },
        activated() {
            this.searchFormInfos.children[3].options.pointType = '0'
            this.searchFields.tagNames = ''
        },
        destroyed() {
            this.restInterval()
        },
    };
    </script>
    <style lang="scss">
    @import '@frameworks/assets/css/common.scss';
    .chart-page {
        box-shadow: 0 0 6px 1px rgba(0, 0, 0, 0.1);
        border-radius: 8px;
        height: 500px;
        padding: 20px;
        margin-right: 20px;
    }
    </style>
    View Code

  • 相关阅读:
    【剑指offer】10 矩形覆盖
    【剑指offer】09 变态跳台阶
    【剑指offer】08 跳台阶
    【剑指offer】07 斐波那契数列
    【剑指offer】06 旋转数组的最小数字
    【剑指offer】05 用两个栈实现队列
    【剑指offer】04 重建二叉树
    【剑指offer】03 从尾到头打印链表
    【剑指offer】02 替换空格
    【剑指offer】01 二维数组中的查找
  • 原文地址:https://www.cnblogs.com/pengfei25/p/14168716.html
Copyright © 2011-2022 走看看