|
|
@@ -29,27 +29,78 @@
|
|
|
<el-row class="movie-list">
|
|
|
<el-card>
|
|
|
<div slot="header" class="clearfix">
|
|
|
- <span>饼图</span>
|
|
|
+ <span style="margin-right: 5px">选择图表</span>
|
|
|
+ <el-select
|
|
|
+ v-model="selectedValue"
|
|
|
+ clearable
|
|
|
+ placeholder="选择图表"
|
|
|
+ @change="onSelectChange"
|
|
|
+ >
|
|
|
+ <el-option label="考试通过率" value="1" />
|
|
|
+ <el-option label="考试次数占比" value="2" />
|
|
|
+ <el-option label="考试通过率折线图" value="3" />
|
|
|
+ <el-option label="新用户激活数" value="4" />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
- <div id="chart4" style="width: 800px;height:400px;" />
|
|
|
+ <div id="chart4" style="height:400px;" />
|
|
|
</el-card>
|
|
|
</el-row>
|
|
|
+ <el-row class="movie-list">
|
|
|
+ <el-col :md="12" class="movie-list">
|
|
|
+ <el-card>
|
|
|
+ <div id="chart5" style="height:400px;" />
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ <el-col :md="12" class="movie-list">
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col class="movie-list" :md="12">
|
|
|
+ <el-card>
|
|
|
+ <div id="chart7" style="width: 600px;height:400px;" />
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ <el-col class="movie-list" :md="12">
|
|
|
+ <el-card>
|
|
|
+ <div id="chart8" style="width: 600px;height:400px;" />
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
</el-row>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import * as echarts from 'echarts'
|
|
|
+import { getExamCount, getExamPassRate, getLineChartData } from '@/api/exam'
|
|
|
+import { getUserWatch, getUserWatchRegion } from '@/api/analysis'
|
|
|
|
|
|
export default {
|
|
|
name: 'LineChart',
|
|
|
data() {
|
|
|
return {
|
|
|
+ // 考试名称
|
|
|
+ examNames: [],
|
|
|
+ // 考试通过率
|
|
|
+ passRate: [],
|
|
|
+ // 饼图的数据
|
|
|
+ pieData: [],
|
|
|
+ selectedValue: '1',
|
|
|
+ chartOption: null,
|
|
|
+ barChartNames: [],
|
|
|
+ barChartData: [],
|
|
|
+ pieChartNames: [],
|
|
|
+ pieChartData: [],
|
|
|
+ chartOption1: null
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
|
this.initChart1()
|
|
|
this.initChart2()
|
|
|
this.initChart3()
|
|
|
+ this.getExamPassRate()
|
|
|
+ this.getExamNumbers()
|
|
|
+ this.getUserWatchWrapper()
|
|
|
+ this.getUserWatchRegionWrapper()
|
|
|
},
|
|
|
created() {
|
|
|
document.title = 'LineChart'
|
|
|
@@ -309,6 +360,397 @@ export default {
|
|
|
myChart.resize()
|
|
|
}
|
|
|
})
|
|
|
+ },
|
|
|
+ handleChange(val) {
|
|
|
+ this.$message.info('select -> ' + val)
|
|
|
+ },
|
|
|
+ onSelectChange() {
|
|
|
+ this.getExamPassRate()
|
|
|
+ },
|
|
|
+ async getExamPassRate() {
|
|
|
+ await getExamPassRate().then((resp) => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.examNames = resp.data[0].split(',')
|
|
|
+ this.passRate = resp.data[1].split(',')
|
|
|
+
|
|
|
+ const intValue = parseInt(this.selectedValue)
|
|
|
+ if (intValue === 1) {
|
|
|
+ this.drawLine()
|
|
|
+ } else if (intValue === 2) {
|
|
|
+ this.drawBrokenLine()
|
|
|
+ } else if (intValue === 3) {
|
|
|
+ this.drawImg4()
|
|
|
+ } else {
|
|
|
+ // this.drawChart5()
|
|
|
+ this.drawChart6()
|
|
|
+ }
|
|
|
+
|
|
|
+ const myChart = this.$echarts.init(document.getElementById('chart4'))
|
|
|
+ // setOption 是 merge,而非赋值, setOption 支持 notMerge 参数, 值为 true 时重新渲染
|
|
|
+ myChart.setOption(this.chartOption, true)
|
|
|
+ this.loading.close()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 考试通过率柱状图
|
|
|
+ drawLine() {
|
|
|
+ this.chartOption = {
|
|
|
+ title: {
|
|
|
+ text: '考试通过率',
|
|
|
+ subtext: 'dashbord1',
|
|
|
+ x: 'center',
|
|
|
+ y: 'top',
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {},
|
|
|
+ xAxis: {
|
|
|
+ data: this.examNames
|
|
|
+ },
|
|
|
+ yAxis: {},
|
|
|
+ series: [{
|
|
|
+ name: '通过率',
|
|
|
+ type: 'bar',
|
|
|
+ data: this.passRate
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 通过率的折线图
|
|
|
+ drawBrokenLine() {
|
|
|
+ this.chartOption = {
|
|
|
+ // 标题
|
|
|
+ title: {
|
|
|
+ text: '考试通过率折线图',
|
|
|
+ x: 'center'
|
|
|
+ },
|
|
|
+ // x轴
|
|
|
+ xAxis: {
|
|
|
+ data: this.examNames
|
|
|
+ },
|
|
|
+ // y轴没有显式设置,根据值自动生成y轴
|
|
|
+ yAxis: {},
|
|
|
+ // 数据-data是最终要显示的数据
|
|
|
+ series: [{
|
|
|
+ name: '通过率',
|
|
|
+ type: 'line',
|
|
|
+ areaStyle: {
|
|
|
+ normal: {}
|
|
|
+ },
|
|
|
+ data: this.passRate
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drawImg4() {
|
|
|
+ this.chartOption = {
|
|
|
+ color: ['#cd5c5c'],
|
|
|
+ textStyle: {
|
|
|
+ color: 'black'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'shadow'
|
|
|
+ },
|
|
|
+ formatter: '{a} <br/>{b} : {c}'
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'value',
|
|
|
+ boundaryGap: [0, 0.01],
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 'axisLabel': {
|
|
|
+ 'interval': 0,
|
|
|
+ fontSize: 18,
|
|
|
+ formatter: '{value}'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 'axisLabel': {
|
|
|
+ 'interval': 0,
|
|
|
+ fontSize: 18
|
|
|
+ },
|
|
|
+ type: 'category',
|
|
|
+ data: this.examNames
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ name: '通过率:',
|
|
|
+ type: 'bar',
|
|
|
+ data: this.passRate
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drawChart5() {
|
|
|
+ this.chartOption = {
|
|
|
+ title: {
|
|
|
+ text: '卡拉云新用户激活数据',
|
|
|
+ subtext: 'Demo 虚构数据',
|
|
|
+ x: 'center'
|
|
|
+ },
|
|
|
+ legend: { // 图例配置选项
|
|
|
+ orient: 'horizontal', // 图例布局方式:水平 'horizontal' 、垂直 'vertical'
|
|
|
+ x: 'left', // 横向放置位置,选项:'center'、'left'、'right'、'number'(横向值 px)
|
|
|
+ y: 'top', // 纵向放置位置,选项:'top'、'bottom'、'center'、'number'(纵向值 px)
|
|
|
+ data: ['猜想', '预期', '实际']
|
|
|
+ },
|
|
|
+ grid: { // 图表距离边框的距离,可用百分比和数字(px)配置
|
|
|
+ top: '20%',
|
|
|
+ left: '3%',
|
|
|
+ right: '10%',
|
|
|
+ bottom: '5%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ name: '月份',
|
|
|
+ type: 'category',
|
|
|
+ data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ name: '人次',
|
|
|
+ type: 'value',
|
|
|
+ min: 0, // 配置 Y 轴刻度最小值
|
|
|
+ max: 4000, // 配置 Y 轴刻度最大值
|
|
|
+ splitNumber: 7 // 配置 Y 轴数值间隔
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '猜想',
|
|
|
+ data: [454, 226, 891, 978, 901, 581, 400, 543, 272, 955, 1294, 1581],
|
|
|
+ type: 'line',
|
|
|
+ symbolSize: function(value) { // 点的大小跟随数值增加而变大
|
|
|
+ return value / 150
|
|
|
+ },
|
|
|
+ symbol: 'circle',
|
|
|
+ itemStyle: {
|
|
|
+ normal: {
|
|
|
+ label: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(0,0,0,0)'// 折线颜色设置为0,即只显示点,不显示折线
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '预期',
|
|
|
+ data: [2455, 2534, 2360, 2301, 2861, 2181, 1944, 2197, 1745, 1810, 2283, 2298],
|
|
|
+ type: 'line',
|
|
|
+ symbolSize: 8, // 设置折线上圆点大小
|
|
|
+ itemStyle: {
|
|
|
+ normal: {
|
|
|
+ label: {
|
|
|
+ show: true // 在折线拐点上显示数据
|
|
|
+ },
|
|
|
+ lineStyle: {
|
|
|
+ width: 3, // 设置虚线宽度
|
|
|
+ type: 'dotted' // 虚线'dotted' 实线'solid'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '实际',
|
|
|
+ data: [1107, 1352, 1740, 1968, 1647, 1570, 1343, 1757, 2547, 2762, 3170, 3665],
|
|
|
+ type: 'line',
|
|
|
+ symbol: 'circle', // 实心圆点
|
|
|
+ smooth: 0.5 // 设置折线弧度
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ color: ['#3366CC', '#FFCC99', '#99CC33'] // 三个折线的颜色
|
|
|
+ }
|
|
|
+ },
|
|
|
+ drawChart6() {
|
|
|
+ getLineChartData().then(resp => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ const data = resp.data
|
|
|
+ this.chartOption = {
|
|
|
+ title: {
|
|
|
+ text: '卡拉云新用户激活数据',
|
|
|
+ subtext: 'Demo 虚构数据',
|
|
|
+ x: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {},
|
|
|
+ legend: { // 图例配置选项
|
|
|
+ orient: 'horizontal', // 图例布局方式:水平 'horizontal' 、垂直 'vertical'
|
|
|
+ x: 'left', // 横向放置位置,选项:'center'、'left'、'right'、'number'(横向值 px)
|
|
|
+ y: 'top', // 纵向放置位置,选项:'top'、'bottom'、'center'、'number'(纵向值 px)
|
|
|
+ data: ['实际']
|
|
|
+ },
|
|
|
+ grid: { // 图表距离边框的距离,可用百分比和数字(px)配置
|
|
|
+ top: '20%',
|
|
|
+ left: '3%',
|
|
|
+ right: '10%',
|
|
|
+ bottom: '5%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ name: data.xName,
|
|
|
+ type: 'category',
|
|
|
+ data: data.xLabel
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ name: data.yName,
|
|
|
+ type: 'value',
|
|
|
+ min: data.yMin, // 配置 Y 轴刻度最小值
|
|
|
+ max: data.yMax, // 配置 Y 轴刻度最大值
|
|
|
+ splitNumber: data.ySplitNumber // 配置 Y 轴数值间隔
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '实际',
|
|
|
+ data: data.xValue,
|
|
|
+ type: 'line',
|
|
|
+ symbol: 'circle', // 实心圆点
|
|
|
+ smooth: 0.5 // 设置折线弧度
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ color: ['#99CC33'] // 三个折线的颜色
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 获取考试次数数据
|
|
|
+ async getExamNumbers() {
|
|
|
+ await getExamCount().then((resp) => {
|
|
|
+ const examNames = resp.data[0].split(',')
|
|
|
+ const examNumbers = resp.data[1].split(',')
|
|
|
+ examNames.forEach((item, index) => {
|
|
|
+ this.pieData.push({
|
|
|
+ name: item,
|
|
|
+ value: parseInt(examNumbers[index])
|
|
|
+ })
|
|
|
+ })
|
|
|
+ this.drawPie()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 考试次数饼图
|
|
|
+ drawPie() {
|
|
|
+ // 基于准备好的dom,初始化echarts实例
|
|
|
+ const myChart = this.$echarts.init(document.getElementById('chart5'))
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: '考试次数占比',
|
|
|
+ subtext: 'dashbord2',
|
|
|
+ x: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item',
|
|
|
+ formatter: '{a} <br/>{b} : {c}次 ({d}%)'
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ orient: 'vertical',
|
|
|
+ left: 'left',
|
|
|
+ data: this.pieData
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '考试次数',
|
|
|
+ type: 'pie',
|
|
|
+ radius: '55%',
|
|
|
+ data: this.pieData,
|
|
|
+ roseType: 'angle',
|
|
|
+ itemStyle: {
|
|
|
+ normal: {
|
|
|
+ shadowBlur: 200,
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ myChart.setOption(option)
|
|
|
+ },
|
|
|
+ async getUserWatchWrapper() {
|
|
|
+ await getUserWatch().then((resp) => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.barChartNames = resp.data[0].split(',')
|
|
|
+ this.barChartData = resp.data[1].split(',')
|
|
|
+ this.drawBarChart()
|
|
|
+ const myChart = this.$echarts.init(document.getElementById('chart7'))
|
|
|
+ // setOption 是 merge,而非赋值, setOption 支持 notMerge 参数, 值为 true 时重新渲染
|
|
|
+ myChart.setOption(this.chartOption1, true)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ drawBarChart() {
|
|
|
+ this.chartOption1 = {
|
|
|
+ title: {
|
|
|
+ text: '观看时长',
|
|
|
+ subtext: '最近一周',
|
|
|
+ x: 'center',
|
|
|
+ y: 'top',
|
|
|
+ textAlign: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {},
|
|
|
+ xAxis: {
|
|
|
+ data: this.barChartNames
|
|
|
+ },
|
|
|
+ yAxis: {},
|
|
|
+ series: [{
|
|
|
+ name: '时长',
|
|
|
+ type: 'bar',
|
|
|
+ data: this.barChartData
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getUserWatchRegionWrapper() {
|
|
|
+ await getUserWatchRegion().then((resp) => {
|
|
|
+ const pieNames = resp.data[0].split(',')
|
|
|
+ const pieNumbers = resp.data[1].split(',')
|
|
|
+ pieNames.forEach((item, index) => {
|
|
|
+ this.pieChartData.push({
|
|
|
+ name: item,
|
|
|
+ value: parseInt(pieNumbers[index])
|
|
|
+ })
|
|
|
+ })
|
|
|
+ this.drawPieChart()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ drawPieChart() {
|
|
|
+ // 基于准备好的dom,初始化echarts实例
|
|
|
+ const myChart = this.$echarts.init(document.getElementById('chart8'))
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: '分区占比',
|
|
|
+ subtext: '视频分区',
|
|
|
+ x: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item',
|
|
|
+ formatter: '{a} <br/>{b} : {c}次 ({d}%)'
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ orient: 'vertical',
|
|
|
+ left: 'left',
|
|
|
+ data: this.pieChartData
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '时长',
|
|
|
+ type: 'pie',
|
|
|
+ radius: '55%',
|
|
|
+ data: this.pieChartData,
|
|
|
+ roseType: 'angle',
|
|
|
+ itemStyle: {
|
|
|
+ normal: {
|
|
|
+ shadowBlur: 200,
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ myChart.setOption(option)
|
|
|
}
|
|
|
}
|
|
|
}
|