Open deligent-ant opened 6 years ago
主要使用 frappe-chart 组件,对其做了一个简单封装。主要提供以下几个功能。
chartData: {} chartConfig:{}
chartData与chartConfig设置和官网一样 主要增加如下配置 chartConfig: { btnOptions: { sizeBtn: false,//{ show: true,} exportBtn: { show: true, type: 'data', xlabel: '时间' } }, showMax_Min_Mean: { max: false, min: false, mean: false }}
chartData与chartConfig设置和官网一样 主要增加如下配置
chartConfig: { btnOptions: { sizeBtn: false,//{ show: true,} exportBtn: { show: true, type: 'data', xlabel: '时间' } }, showMax_Min_Mean: { max: false, min: false, mean: false }}
<template> <div :class="{component_chart:true,chartLarge:hasLarged}" v-if="chartShow"> <div class="chartWrap" ref="chartWrap"> <div class="chart" ref="chart"> </div> <!-- 扩展的按钮 --> <div class="anatherBtn"> <slot> </slot> </div> <div :class="{largeBtn:(chartConfig.btnOptions||{}).sizeBtn, chartBtn:true}" @click="changeSize" v-if="(chartConfig.btnOptions||{}).sizeBtn"> <i class="el-icon-rank"></i> </div> <div :class="{downloadBtn:(chartConfig.btnOptions||{}).exportBtn, chartBtn:true}" @click="exportChart" v-if="((chartConfig.btnOptions||{}).exportBtn||{}).show&&chartConfig.btnOptions.exportBtn.type=='pic'"> <i class="el-icon-download"></i> </div> <out-put :class="{downloadBtn:(chartConfig.btnOptions||{}).exportBtn, chartBtn:true}" :params="outputParams" v-if="((chartConfig.btnOptions||{}).exportBtn||{}).show&&chartConfig.btnOptions.exportBtn.type=='data'"> <i class="el-icon-download"></i> </out-put> </div> </div> </template> <script> import _ from 'lodash' import OutPut from '~/components/common/outputXLSX' import { Chart } from 'frappe-charts' export default { data() { return { chartShow: true, chartDom: {}, hasLarged: false, chart: {}, config: {} } }, props: { chartData: { type: Object, default: () => ({}) }, chartConfig: { type: Object, default: () => ({}) } }, computed: { outputParams() { let jsonData = [] let keyMap = { xlabel: ((this.chartConfig.btnOptions || {}).exportBtn || {}).xlabel } //验证数据格式 if ( !( Array.isArray(this.chartData.datasets) && this.chartData.datasets.length && Array.isArray(this.chartData.labels) && this.chartData.labels.length ) ) { return { jsonData, keyMap } } this.chartData.datasets.forEach((line, index) => { keyMap['key' + index] = line.name }) this.chartData.labels.forEach((x, i) => { let oneRow = {} oneRow.xlabel = x this.chartData.datasets.forEach((line, index) => { oneRow['key' + index] = line.values[i] }) jsonData.push(oneRow) }) return { jsonData, keyMap, fileName: this.chartConfig.title } } }, watch: { chartData(newValue, oldValue) { let chartDom = this.$refs.chart if ( Array.isArray(newValue.labels) && Array.isArray(oldValue.labels) && newValue.labels.length == oldValue.labels.length && newValue.datasets.length == oldValue.datasets.length ) { this.chart.update(newValue) } else { this.initChart() } } }, components: { OutPut }, methods: { changeSize() { this.hasLarged = !this.hasLarged if (this.hasLarged) { this.$set(this.config, 'height', this.config.height * 2) } else { this.$set(this.config, 'height', this.chartConfig.height) } this.initChart(true) }, exportChart() { this.chart.export() }, initChart(isSize) { if (!isSize) { this.config = _.cloneDeep(this.chartConfig) } //验证数据格式 if ( !( Array.isArray(this.chartData.datasets) && this.chartData.datasets.length && Array.isArray(this.chartData.labels) && this.chartData.labels.length ) ) { return } //单点情况 if (this.chartData.labels.length == 1) { this.chartData.labels.push('') if (this.config.type == 'line') { this.config.lineOptions = { dotSize: 4, hideDots: 0 } } else if (this.config.type == 'bar') { this.config.barOptions = {} } } else { if (!isSize) { this.config = _.cloneDeep(this.chartConfig) } } let allData = [] this.chartData.datasets.forEach(element => { allData.push(...element.values) }) //确保坐标最大值和最小值能显示 if (this.chartConfig.showMax_Min_Mean) { if ( !(this.chartData.yMarkers && Array.isArray(this.chartData.yMarkers)) ) { this.chartData.yMarkers = [] } if (this.chartConfig.showMax_Min_Mean.max) { this.chartData.yMarkers.push({ label: 'max', value: Math.max(...allData), options: { labelPos: 'left' } }) } if (this.chartConfig.showMax_Min_Mean.min) { this.chartData.yMarkers.push({ label: 'min', value: Math.min(...allData), options: { labelPos: 'left' } }) } if (this.chartConfig.showMax_Min_Mean.mean) { let sum = 0 allData.forEach(item => { sum += item }) this.chartData.yMarkers.push({ label: 'mean', value: sum / allData.length, options: { labelPos: 'left' } }) } } if ( this.chartData.labels.length < 15 && this.config.lineOptions && !this.config.lineOptions.hideDots ) { this.chartConfig.lineOptions.dotSize = 4 } setTimeout(() => { this.chart = new Chart(this.chartDom, { data: this.chartData, ...this.config }) }, 50) } }, mounted() { let chartDom = this.$refs.chart this.chartDom = chartDom this.initChart() }, beforeDestroy() { //离开时候 注销chart if ( this.chart.unbindWindowEvents && typeof this.chart.unbindWindowEvents == 'function' ) { this.chart.unbindWindowEvents() } } } </script> <style lang="stylus"> .chart .frappe-chart.chart text.title font-size 14px fill rgb(34 34 34) </style> <style scoped lang="stylus"> .component_chart font-family 'PingFangSC-Regular' display flex flex-direction column justify-content center width 100% overflow hidden .chartWrap position relative text-align center overflow hidden .chart width 100% .chartBtn font-size 18px padding 2px 5px position absolute color rgb(182 192 226) &:hover cursor pointer .largeBtn top 10px right 1px .downloadBtn bottom 0px right 1px .anatherBtn position absolute top 4px left 115px // top 10px // right 60px .chartLarge width 970px height 500px .largeBtn top 10px right 20px!important .downloadBtn bottom 0px right 20px!important </style>
2B的报表组件
主要属性
组件比较简短粗燥 ,所以直接端上来了。