<template> <div style="height: 100%; width: 100%"> <div class="chart-title"> <div class="name" :title="title"> {{ title }} </div> <div class="operation"> <!-- <el-button size="mini" plain @click="initChart()"> <span class="icon iconfont icontjfx"></span> </el-button> <el-button size="mini" plain @click="initTable()"> <span class="icon iconfont icontongjibiao"></span> </el-button> --> <el-radio v-model="showType" label="chart">chart</el-radio> <el-radio v-model="showType" label="table">表格</el-radio> <div class="operation-btn" @click="downLoadInfo()"> <img class="icon" :src="require('../../images/download.png')" /> <label>下载</label> </div> <!-- <div class="operation-btn"> <img class="icon" :src="require('../../images/expand.png')" /> <label>展开</label> </div> --> </div> </div> <div class="dataContainer"> <div class="IndexLineChart" ref="chart" v-if="!isShowTable"></div> <el-table id="dataTable" :data="tableData" v-if="isShowTable" style="width: 100%; height: 100%; overflow: auto"> <el-table-column v-for="item of tabelColumn" :key="item.value" :prop="item.prop" :label="item.label" show-overflow-tooltip ></el-table-column> </el-table> </div> </div> </template> <script lang='ts'> import echarts, { ECharts } from 'echarts' import html2canvas from 'html2canvas' import XLSX from 'xlsx' import FileSaver from 'file-saver' import { Vue, Component, Prop, Watch } from 'vue-property-decorator' @Component({ name: 'IndexLineChart', components: {} }) export default class IndexLineChart extends Vue { @Prop({ type: Object, default: () => ({}) }) chartData!: any @Watch('chartData', { immediate: true }) onChangeMethod() { this.$nextTick(() => { this.initialChart() }) } @Prop({ type: Boolean, default: false }) isActive!: boolean @Watch('isActive', { immediate: true }) refetchData(active: boolean) { if (active) this.onResize() } get title() { return `${this.chartData.siteName}:${this.chartData.indexName}${ this.chartData.unit ? `(${this.chartData.unit})` : '' }` } myChart = null isShowTable = false tableData = [] tabelColumn = [ { prop: 'siteName', label: '厂站' }, { prop: 'indexName', label: '指标' }, { prop: 'staType', label: '统计内容' }, { prop: 'data', label: '指标值' }, { prop: 'time', label: '时间' } ] showType = 'chart' @Watch('showType', { immediate: true }) showTypeChangeMethod(type) { this.$nextTick(() => { type == 'chart' ? this.initChart() : this.initTable() }) } destroyChart() { if (this.myChart != null) { this.myChart.dispose() this.myChart = null } } onResize() { if (this.myChart) { this.myChart.resize() } } initialChart() { this.destroyChart() const { xData: xaxis, seriesData, tableData, siteName, indexName } = this.chartData //表格数据 this.tableData = tableData.map((i) => { return { ...i, siteName, indexName } }) // let seriesValue = [] seriesData.forEach((item) => { seriesValue.push({ name: item.name, data: item.data, type: 'line', smooth: true // symbol: 'none' }) }) let option = { grid: { bottom: 20, top: 50, right: 20, left: 20, containLabel: true }, tooltip: { trigger: 'axis' }, xAxis: { type: 'category', axisLine: { show: false }, axisTick: { show: false }, data: xaxis }, yAxis: { type: 'value', name: '', nameTextStyle: { padding: [0, 0, 0, -40], align: 'left', color: '#2D74E7', fontWeight: '500', fontSize: '14', fontFamily: 'Source Han Sans CN' }, nameGap: 30, axisLine: { show: false }, axisTick: { show: false } }, series: seriesValue } this.creatChart(option, this.$refs.chart) } creatChart(option, ref) { this.myChart = echarts.init(ref) //this.$refs.chart this.myChart.resize() this.myChart.setOption(option, { notMerge: true }) //图表大小自适应 window.addEventListener('resize', () => { this.myChart.resize() }) } initTable() { this.isShowTable = true } initChart() { this.isShowTable = false this.$nextTick(() => { this.initialChart() }) } //下载 downLoadInfo() { if (this.isShowTable) { this.exportTable() } else { this.exportChart() } } exportTable() { let wb = XLSX.utils.table_to_book(document.querySelector('#dataTable'), { raw: true }) let wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' }) try { FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '数据表格.xlsx') } catch (e) { if (typeof console !== 'undefined') console.log(e, wbout) } return wbout } exportChart() { // 图表转换成canvas //@ts-ignore html2canvas(this.$refs.chart).then(function (canvas) { var img = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream') // 创建a标签,实现下载 var creatIMg = document.createElement('a') creatIMg.download = `图表.png` // 设置下载的文件名, creatIMg.href = img // 下载url document.body.appendChild(creatIMg) creatIMg.click() creatIMg.remove() // 下载之后把创建的元素删除 }) } } </script> <style lang="scss" scoped> .chart-title { display: flex; justify-content: space-between; align-items: center; font-size: 16px; position: relative; margin-top: 10px; height: 20px; .name { font-family: Source Han Sans CN-Medium; font-style: normal; font-weight: 500; font-size: 14px; color: #2d74e7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .operation { // position: absolute; // right: 0; // z-index: 999; display: flex; align-items: center; @mixin font() { color: #333333; font-family: Source Han Sans CN; font-style: normal; font-weight: 400; font-size: 14px; } .el-button { padding: 2px; border: none; color: #333333; } >>> .el-radio { .el-radio__label { @include font(); padding-left: 5px; } .el-radio__inner::after { height: 8px; width: 8px; background-color: #2083e8; } .el-radio__inner { border: 1px solid rgba(128, 175, 214, 1); background-color: transparent; } } .operation-btn { display: flex; align-items: center; cursor: pointer; margin-right: 30px; .icon { height: 14px; width: 14px; margin-right: 5px; } label { @include font(); cursor: pointer; white-space: nowrap; } } } } .dataContainer { width: 100%; height: calc(100% - 30px); .IndexLineChart { width: 100%; height: 100%; } } </style>