桑基图优化
This commit is contained in:
		
							parent
							
								
									a121765433
								
							
						
					
					
						commit
						719ff5de46
					
				
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
								
							@ -1,18 +1,25 @@
 | 
				
			|||||||
  
 | 
					  
 | 
				
			||||||
 | 
					 ## 铸龙-用户行为分析系统
 | 
				
			||||||
技术栈主要用: Vue + golang 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
欢迎大家提出自己的issue。
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
铸龙-用户事件分析系统
 | 
					 | 
				
			||||||
-----------
 | 
					-----------
 | 
				
			||||||
> 铸龙-用户事件分析系统 是一款用来进行分析用户行为事件的BI软件,功能如下
 | 
					> 铸龙-用户行为分析系统 是一款用于分析用户行为事件的BI软件,功能如下
 | 
				
			||||||
 * 事件分析
 | 
					 * 事件分析
 | 
				
			||||||
 * 漏斗分析
 | 
					 * 漏斗分析
 | 
				
			||||||
 * 留存分析
 | 
					 * 留存分析
 | 
				
			||||||
 * 智能路径分析
 | 
					 * 智能路径分析
 | 
				
			||||||
 * 报表,面板管理
 | 
					 * 报表,面板管理
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 技术栈主要用
 | 
				
			||||||
 | 
					 * 前端:vue+elementui+antdv
 | 
				
			||||||
 | 
					 * 后端:go
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					> 所需中间件
 | 
				
			||||||
 | 
					 * mysql
 | 
				
			||||||
 | 
					 * redis
 | 
				
			||||||
 | 
					 * kafka
 | 
				
			||||||
 | 
					 * clickhouse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					欢迎大家提出自己的issue。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 相关
 | 
					## 相关
 | 
				
			||||||
[下载地址]( https://gitee.com/cynthia520/xwl_bi/releases/v1.0.0 ) 
 | 
					[下载地址]( https://gitee.com/cynthia520/xwl_bi/releases/v1.0.0 ) 
 | 
				
			||||||
[文档地址]( https://www.yuque.com/jianghurenchenggolang/oehqme/hen7qy ) 
 | 
					[文档地址]( https://www.yuque.com/jianghurenchenggolang/oehqme/hen7qy ) 
 | 
				
			||||||
 | 
				
			|||||||
@ -1,176 +1,213 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :id="className" :class="className" :style="{height:height,width:width}" />
 | 
					  <div :class="className" :id="className" :style="{height:height,width:width}"/>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
// import echarts from 'echarts'
 | 
					  // import echarts from 'echarts'
 | 
				
			||||||
// require('echarts/theme/macarons') // echarts theme
 | 
					  //require('echarts/theme/macarons') // echarts theme
 | 
				
			||||||
import resize from './mixins/resize'
 | 
					  import resize from './mixins/resize'
 | 
				
			||||||
import { setNotopt } from './mixins/utils'
 | 
					  import {setNotopt} from './mixins/utils'
 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
  mixins: [resize],
 | 
					 | 
				
			||||||
  props: {
 | 
					 | 
				
			||||||
    className: {
 | 
					 | 
				
			||||||
      type: String,
 | 
					 | 
				
			||||||
      default: 'chart'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    width: {
 | 
					 | 
				
			||||||
      type: String,
 | 
					 | 
				
			||||||
      default: '100%'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    height: {
 | 
					 | 
				
			||||||
      type: String,
 | 
					 | 
				
			||||||
      default: '400px'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    autoResize: {
 | 
					 | 
				
			||||||
      type: Boolean,
 | 
					 | 
				
			||||||
      default: true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    chartData: {
 | 
					 | 
				
			||||||
      type: Array,
 | 
					 | 
				
			||||||
      default: []
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  data() {
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      chart: null
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  watch: {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  },
 | 
					  export default {
 | 
				
			||||||
  mounted() {
 | 
					    mixins: [resize],
 | 
				
			||||||
    this.initChart()
 | 
					    props: {
 | 
				
			||||||
  },
 | 
					      className: {
 | 
				
			||||||
  beforeDestroy() {
 | 
					        type: String,
 | 
				
			||||||
    if (!this.chart) {
 | 
					        default: 'chart'
 | 
				
			||||||
      return
 | 
					      },
 | 
				
			||||||
    }
 | 
					      width: {
 | 
				
			||||||
    this.chart.dispose()
 | 
					        type: String,
 | 
				
			||||||
    this.chart = null
 | 
					        default: '100%'
 | 
				
			||||||
  },
 | 
					      },
 | 
				
			||||||
  methods: {
 | 
					      height: {
 | 
				
			||||||
    initChart() {
 | 
					        type: String,
 | 
				
			||||||
      this.chart = echarts.init(document.getElementById(this.className))
 | 
					        default: '400px'
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      this.setOptions()
 | 
					      autoResize: {
 | 
				
			||||||
 | 
					        type: Boolean,
 | 
				
			||||||
 | 
					        default: true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      chartData: {
 | 
				
			||||||
 | 
					        type: Array,
 | 
				
			||||||
 | 
					        default: []
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    setOptions() {
 | 
					    data() {
 | 
				
			||||||
      if (this.chartData.length == 0) {
 | 
					      return {
 | 
				
			||||||
        setNotopt(this.chart)
 | 
					        chart: null
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    watch: {},
 | 
				
			||||||
 | 
					    mounted() {
 | 
				
			||||||
 | 
					      this.initChart()
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    beforeDestroy() {
 | 
				
			||||||
 | 
					      if (!this.chart) {
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      this.chart.dispose()
 | 
				
			||||||
      const eventArr = []
 | 
					      this.chart = null
 | 
				
			||||||
      const targetArr = []
 | 
					 | 
				
			||||||
      const eventSet = new Map()
 | 
					 | 
				
			||||||
      for (const k in this.chartData) {
 | 
					 | 
				
			||||||
        const traceCharts = this.chartData[k]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        eventSet.set(traceCharts['event'][0], 1)
 | 
					 | 
				
			||||||
        eventSet.set(traceCharts['event'][1], 1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        targetArr.push({
 | 
					 | 
				
			||||||
          source: traceCharts['event'][0],
 | 
					 | 
				
			||||||
          target: traceCharts['event'][1],
 | 
					 | 
				
			||||||
          value: traceCharts['sum_user_count']
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      eventSet.forEach((v, k, tmp) => {
 | 
					 | 
				
			||||||
        const obj = {
 | 
					 | 
				
			||||||
          name: k
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        eventArr.push(obj)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const option = {
 | 
					 | 
				
			||||||
        toolbox: {
 | 
					 | 
				
			||||||
          feature: {
 | 
					 | 
				
			||||||
            saveAsImage: {}
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        tooltip: {
 | 
					 | 
				
			||||||
          trigger: 'item',
 | 
					 | 
				
			||||||
          triggerOn: 'mousemove'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        series: [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            type: 'sankey',
 | 
					 | 
				
			||||||
            emphasis: {
 | 
					 | 
				
			||||||
              focus: 'adjacency'
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            nodeAlign: 'left',
 | 
					 | 
				
			||||||
            data: eventArr,
 | 
					 | 
				
			||||||
            links: targetArr,
 | 
					 | 
				
			||||||
            lineStyle: {
 | 
					 | 
				
			||||||
              color: 'source',
 | 
					 | 
				
			||||||
              curveness: 0.5
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        this.chart.setOption(
 | 
					 | 
				
			||||||
          option
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
      } catch (e) {
 | 
					 | 
				
			||||||
        this.setOptions2()
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    setOptions2() {
 | 
					    methods: {
 | 
				
			||||||
      const eventArr = []
 | 
					      initChart() {
 | 
				
			||||||
      const targetArr = []
 | 
					        this.chart = echarts.init(document.getElementById(this.className))
 | 
				
			||||||
      const eventSet = new Map()
 | 
					 | 
				
			||||||
      for (const k in this.chartData) {
 | 
					 | 
				
			||||||
        const traceCharts = this.chartData[k]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        eventSet.set(traceCharts['event'][0] + ' ', 1)
 | 
					        this.setOptions()
 | 
				
			||||||
        eventSet.set(traceCharts['event'][1] + '  ', 1)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        targetArr.push({
 | 
					      },
 | 
				
			||||||
          source: traceCharts['event'][0] + ' ',
 | 
					      getColor1() {//固定红色值
 | 
				
			||||||
          target: traceCharts['event'][1] + '  ',
 | 
					        var re = "#";
 | 
				
			||||||
          value: traceCharts['sum_user_count']
 | 
					        var col = this.color();
 | 
				
			||||||
        })
 | 
					        re += col + "FF";
 | 
				
			||||||
      }
 | 
					        return re
 | 
				
			||||||
      eventSet.forEach((v, k, tmp) => {
 | 
					      },
 | 
				
			||||||
        const obj = {
 | 
					      getColor2() {//固定蓝色值
 | 
				
			||||||
          name: k
 | 
					        var re = "#FF";
 | 
				
			||||||
        }
 | 
					        var col = this.color();
 | 
				
			||||||
        eventArr.push(obj)
 | 
					        re += col;
 | 
				
			||||||
      })
 | 
					        return re
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const option = {
 | 
					      color() {
 | 
				
			||||||
        toolbox: {
 | 
					        var re = "";
 | 
				
			||||||
          feature: {
 | 
					        for (var loopNum = 0; loopNum < 2; loopNum++) {
 | 
				
			||||||
            saveAsImage: {}
 | 
					          var temp = Math.floor(256 * Math.random());
 | 
				
			||||||
 | 
					          if (temp < 130 && loopNum == 0) {
 | 
				
			||||||
 | 
					            temp = 130;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					          if (temp > 200 && loopNum == 1) {
 | 
				
			||||||
        tooltip: {
 | 
					            temp = 200;
 | 
				
			||||||
          trigger: 'item',
 | 
					          }
 | 
				
			||||||
          triggerOn: 'mousemove'
 | 
					          temp = temp.toString(16);//将数值转换成16进制
 | 
				
			||||||
        },
 | 
					          if (temp.length !== 2) {
 | 
				
			||||||
        series: [
 | 
					            temp = "0" + temp
 | 
				
			||||||
          {
 | 
					          }
 | 
				
			||||||
            type: 'sankey',
 | 
					          re += temp//对颜色进行拼接
 | 
				
			||||||
            emphasis: {
 | 
					        }
 | 
				
			||||||
              focus: 'adjacency'
 | 
					        return re;
 | 
				
			||||||
            },
 | 
					      },
 | 
				
			||||||
            nodeAlign: 'left',
 | 
					
 | 
				
			||||||
            data: eventArr,
 | 
					      setOptions() {
 | 
				
			||||||
            links: targetArr,
 | 
					        if (this.chartData.length == 0) {
 | 
				
			||||||
            lineStyle: {
 | 
					          setNotopt(this.chart)
 | 
				
			||||||
              color: 'source',
 | 
					          return
 | 
				
			||||||
              curveness: 0.5
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let eventArr = []
 | 
				
			||||||
 | 
					        let targetArr = []
 | 
				
			||||||
 | 
					        let eventSet = new Map()
 | 
				
			||||||
 | 
					        for (let k in this.chartData) {
 | 
				
			||||||
 | 
					          let traceCharts = this.chartData[k]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          eventSet.set(traceCharts['event'][0], 1)
 | 
				
			||||||
 | 
					          eventSet.set(traceCharts['event'][1], 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          targetArr.push({
 | 
				
			||||||
 | 
					            source: traceCharts['event'][0],
 | 
				
			||||||
 | 
					            target: traceCharts['event'][1],
 | 
				
			||||||
 | 
					            value: traceCharts['sum_user_count'],
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        eventSet.forEach((v, k, tmp) => {
 | 
				
			||||||
 | 
					          let color = ""
 | 
				
			||||||
 | 
					          var random = Math.random();
 | 
				
			||||||
 | 
					          if(random <0.618){//分配红色和蓝色出现的比例
 | 
				
			||||||
 | 
					            color = this.getColor1()
 | 
				
			||||||
 | 
					          }else{
 | 
				
			||||||
 | 
					            color = this.getColor2()
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          let obj = {
 | 
				
			||||||
 | 
					            name: k,
 | 
				
			||||||
 | 
					            itemStyle: {
 | 
				
			||||||
 | 
					              color: color
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ]
 | 
					          eventArr.push(obj)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let levelsArr = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (let i in eventArr) {
 | 
				
			||||||
 | 
					          levelsArr.push({
 | 
				
			||||||
 | 
					            depth: i,
 | 
				
			||||||
 | 
					            itemStyle: {
 | 
				
			||||||
 | 
					              color: eventArr[i].itemStyle.color
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            lineStyle: {
 | 
				
			||||||
 | 
					              color: 'source',
 | 
				
			||||||
 | 
					              opacity: 0.4
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let option = {
 | 
				
			||||||
 | 
					          tooltip: {
 | 
				
			||||||
 | 
					            trigger: 'item',
 | 
				
			||||||
 | 
					            triggerOn: 'mousemove'
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          backgroundColor: '#FFFFFF',
 | 
				
			||||||
 | 
					          series: {
 | 
				
			||||||
 | 
					            type: 'sankey',
 | 
				
			||||||
 | 
					            layout: 'none',
 | 
				
			||||||
 | 
					            top: 50,
 | 
				
			||||||
 | 
					            left: '3%',
 | 
				
			||||||
 | 
					            right: '12%',
 | 
				
			||||||
 | 
					            nodeGap: 14,
 | 
				
			||||||
 | 
					            layoutIterations: 0, // 自动优化列表,尽量减少线的交叉,为0就是按照数据排列
 | 
				
			||||||
 | 
					            data: eventArr, // 节点
 | 
				
			||||||
 | 
					            links: targetArr, // 节点之间的连线
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            focusNodeAdjacency: 'allEdges', // 鼠标划上时高亮的节点和连线,allEdges表示鼠标划到节点上点亮节点上的连线及连线对应的节点
 | 
				
			||||||
 | 
					            levels: [{
 | 
				
			||||||
 | 
					              depth: 0,
 | 
				
			||||||
 | 
					              itemStyle: {
 | 
				
			||||||
 | 
					                color: '#F27E7E'
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: 'source',
 | 
				
			||||||
 | 
					                opacity: 0.4
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                depth: 1,
 | 
				
			||||||
 | 
					                lineStyle: {
 | 
				
			||||||
 | 
					                  color: 'source',
 | 
				
			||||||
 | 
					                  opacity: 0.4
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                depth: 2,
 | 
				
			||||||
 | 
					                lineStyle: {
 | 
				
			||||||
 | 
					                  color: 'source',
 | 
				
			||||||
 | 
					                  opacity: 0.4
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                depth: 3,
 | 
				
			||||||
 | 
					                label: {
 | 
				
			||||||
 | 
					                  fontSize: 12
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            label: {
 | 
				
			||||||
 | 
					              fontSize: 14,
 | 
				
			||||||
 | 
					              color: '#666'
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            itemStyle: {
 | 
				
			||||||
 | 
					              normal: {
 | 
				
			||||||
 | 
					                borderWidth: 0
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          this.chart.setOption(
 | 
				
			||||||
 | 
					            option
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.chart.setOption(
 | 
					 | 
				
			||||||
        option
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user