桑基图优化
This commit is contained in:
		
							parent
							
								
									a121765433
								
							
						
					
					
						commit
						719ff5de46
					
				
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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://www.yuque.com/jianghurenchenggolang/oehqme/hen7qy ) 
 | 
			
		||||
@ -1,176 +1,213 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div :id="className" :class="className" :style="{height:height,width:width}" />
 | 
			
		||||
  <div :class="className" :id="className" :style="{height:height,width:width}"/>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
// import echarts from 'echarts'
 | 
			
		||||
// require('echarts/theme/macarons') // echarts theme
 | 
			
		||||
import resize from './mixins/resize'
 | 
			
		||||
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: {
 | 
			
		||||
  // import echarts from 'echarts'
 | 
			
		||||
  //require('echarts/theme/macarons') // echarts theme
 | 
			
		||||
  import resize from './mixins/resize'
 | 
			
		||||
  import {setNotopt} from './mixins/utils'
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    this.initChart()
 | 
			
		||||
  },
 | 
			
		||||
  beforeDestroy() {
 | 
			
		||||
    if (!this.chart) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    this.chart.dispose()
 | 
			
		||||
    this.chart = null
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initChart() {
 | 
			
		||||
      this.chart = echarts.init(document.getElementById(this.className))
 | 
			
		||||
 | 
			
		||||
      this.setOptions()
 | 
			
		||||
  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: []
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setOptions() {
 | 
			
		||||
      if (this.chartData.length == 0) {
 | 
			
		||||
        setNotopt(this.chart)
 | 
			
		||||
    data() {
 | 
			
		||||
      return {
 | 
			
		||||
        chart: null
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    watch: {},
 | 
			
		||||
    mounted() {
 | 
			
		||||
      this.initChart()
 | 
			
		||||
    },
 | 
			
		||||
    beforeDestroy() {
 | 
			
		||||
      if (!this.chart) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const eventArr = []
 | 
			
		||||
      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()
 | 
			
		||||
      }
 | 
			
		||||
      this.chart.dispose()
 | 
			
		||||
      this.chart = null
 | 
			
		||||
    },
 | 
			
		||||
    setOptions2() {
 | 
			
		||||
      const eventArr = []
 | 
			
		||||
      const targetArr = []
 | 
			
		||||
      const eventSet = new Map()
 | 
			
		||||
      for (const k in this.chartData) {
 | 
			
		||||
        const traceCharts = this.chartData[k]
 | 
			
		||||
    methods: {
 | 
			
		||||
      initChart() {
 | 
			
		||||
        this.chart = echarts.init(document.getElementById(this.className))
 | 
			
		||||
 | 
			
		||||
        eventSet.set(traceCharts['event'][0] + ' ', 1)
 | 
			
		||||
        eventSet.set(traceCharts['event'][1] + '  ', 1)
 | 
			
		||||
        this.setOptions()
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
      })
 | 
			
		||||
      },
 | 
			
		||||
      getColor1() {//固定红色值
 | 
			
		||||
        var re = "#";
 | 
			
		||||
        var col = this.color();
 | 
			
		||||
        re += col + "FF";
 | 
			
		||||
        return re
 | 
			
		||||
      },
 | 
			
		||||
      getColor2() {//固定蓝色值
 | 
			
		||||
        var re = "#FF";
 | 
			
		||||
        var col = this.color();
 | 
			
		||||
        re += col;
 | 
			
		||||
        return re
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      const option = {
 | 
			
		||||
        toolbox: {
 | 
			
		||||
          feature: {
 | 
			
		||||
            saveAsImage: {}
 | 
			
		||||
      color() {
 | 
			
		||||
        var re = "";
 | 
			
		||||
        for (var loopNum = 0; loopNum < 2; loopNum++) {
 | 
			
		||||
          var temp = Math.floor(256 * Math.random());
 | 
			
		||||
          if (temp < 130 && loopNum == 0) {
 | 
			
		||||
            temp = 130;
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
          trigger: 'item',
 | 
			
		||||
          triggerOn: 'mousemove'
 | 
			
		||||
        },
 | 
			
		||||
        series: [
 | 
			
		||||
          {
 | 
			
		||||
            type: 'sankey',
 | 
			
		||||
            emphasis: {
 | 
			
		||||
              focus: 'adjacency'
 | 
			
		||||
            },
 | 
			
		||||
            nodeAlign: 'left',
 | 
			
		||||
            data: eventArr,
 | 
			
		||||
            links: targetArr,
 | 
			
		||||
            lineStyle: {
 | 
			
		||||
              color: 'source',
 | 
			
		||||
              curveness: 0.5
 | 
			
		||||
          if (temp > 200 && loopNum == 1) {
 | 
			
		||||
            temp = 200;
 | 
			
		||||
          }
 | 
			
		||||
          temp = temp.toString(16);//将数值转换成16进制
 | 
			
		||||
          if (temp.length !== 2) {
 | 
			
		||||
            temp = "0" + temp
 | 
			
		||||
          }
 | 
			
		||||
          re += temp//对颜色进行拼接
 | 
			
		||||
        }
 | 
			
		||||
        return re;
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      setOptions() {
 | 
			
		||||
        if (this.chartData.length == 0) {
 | 
			
		||||
          setNotopt(this.chart)
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user