golang实现桑基图,分析用户行为轨迹

本文介绍了如何使用Golang实现桑基图,以分析用户的行为轨迹。首先,通过模拟数据来创建数据库,然后展示了用Golang编写的代码以及对应的HTML文件`sangji.html`和`tongji.html`,最终展示分析效果。

数据库

CREATE TABLE `log` (
  `id` int(11) unsigned NOT NULL DEFAULT '0',
  `event_type` int(11) NOT NULL DEFAULT '1' COMMENT '行为类型: 1:浏览页面 2:点击',
  `uuid` varchar(64) NOT NULL DEFAULT '' COMMENT '访客标识',
  `page` varchar(32) NOT NULL DEFAULT '' COMMENT '访问页面类型ID',
  `client_type` int(11) NOT NULL DEFAULT '0' COMMENT '访问客户端类型, 1:PC 2:移动',
  `client_os` int(11) NOT NULL DEFAULT '0' COMMENT '访客操作系统类型ID',
  `client_browser` int(11) NOT NULL DEFAULT '0' COMMENT '访客浏览器类型ID',
  `client_ip` varchar(64) NOT NULL DEFAULT '' COMMENT '访客IP',
  `client_country` varchar(128) NOT NULL DEFAULT '' COMMENT '访客IP所属国家',
  `client_province` varchar(32) NOT NULL DEFAULT '' COMMENT '访客IP所属省份',
  `client_isp` varchar(32) NOT NULL DEFAULT '' COMMENT '访客IP所属运营商',
  `created_mircotime` bigint(20) NOT NULL DEFAULT '0' COMMENT '访问时间微秒',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '访问时间',
  `view_num` int(11) DEFAULT NULL,
  `path` varchar(300) DEFAULT NULL,
  `full_path` varchar(300) DEFAULT NULL,
  `first_page` varchar(300) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在这里插入图片描述

模拟数据

INSERT INTO `log` (`id`, `event_type`, `uuid`, `page`, `client_type`, `client_os`, `client_browser`, `client_ip`, `client_country`, `client_province`, `client_isp`, `created_mircotime`, `created_at`, `view_num`, `path`, `full_path`, `first_page`)
VALUES
	(1, 1, '36f1a12bcf51d888213fde24759187d0', 'docs', 1, 5, 18, '58.215.154.11', '中国', '浙江', '电信', 16340974537518, '2021-10-13 11:57:33', 1, '开始->docs', 'docs,register,vip,docs_info,login,', 'docs'),
	(2, 1, '36f1a12bcf51d888213fde24759187d0', 'register', 1, 1, 17, '58.215.154.11', '中国', '浙江', '电信', 16340974537566, '2021-10-13 11:57:33', 2, 'docs->register', 'docs,register,vip,docs_info,login,', 'docs'),
	(3, 1, '36f1a12bcf51d888213fde24759187d0', 'vip', 2, 7, 12, '58.215.154.11', '中国', '浙江', '电信', 16340974537602, '2021-10-13 11:57:33', 3, 'register->vip', 'docs,register,vip,docs_info,login,', 'docs'),
	(4, 1, '36f1a12bcf51d888213fde24759187d0', 'docs_info', 1, 5, 2, '58.215.154.11', '中国', '浙江', '电信', 16340974537671, '2021-10-13 11:57:33', 4, 'vip->docs_info', 'docs,register,vip,docs_info,login,', 'docs'),
	(5, 1, '36f1a12bcf51d888213fde24759187d0', 'login', 2, 2, 5, '58.215.154.11', '中国', '浙江', '电信', 16340974537713, '2021-10-13 11:57:33', 5, 'docs_info->login', 'docs,register,vip,docs_info,login,', 'docs'),
	(6, 1, 'b28439abd96a2f19d691691de5a77bde', 'vip', 1, 3, 2, '58.215.154.11', '中国', '浙江', '电信', 16340974537754, '2021-10-13 11:57:33', 1, '开始->vip', 'vip,docs,vip,register,docs,register,', 'vip'),
	(7, 1, 'b28439abd96a2f19d691691de5a77bde', 'docs', 2, 4, 17, '58.215.154.11', '中国', '浙江', '电信', 16340974537778, '2021-10-13 11:57:33', 2, 'vip->docs', 'vip,docs,vip,register,docs,register,', 'vip'),
	(8, 1, 'b28439abd96a2f19d691691de5a77bde', 'vip', 2, 2, 15, '58.215.154.11', '中国', '浙江', '电信', 16340974537807, '2021-10-13 11:57:33', 3, 'docs->vip', 'vip,docs,vip,register,docs,register,', 'vip'),
	(9, 1, 'b28439abd96a2f19d691691de5a77bde', 'register', 1, 9, 1, '58.215.154.11', '中国', '浙江', '电信', 16340974537835, '2021-10-13 11:57:33', 4, 'vip->register', 'vip,docs,vip,register,docs,register,', 'vip'),
	(10, 1, 'b28439abd96a2f19d691691de5a77bde', 'docs', 2, 8, 8, '58.215.154.11', '中国', '浙江', '电信', 16340974537858, '2021-10-13 11:57:33', 5, 'register->docs', 'vip,docs,vip,register,docs,register,', 'vip'),
	(11, 1, 'b28439abd96a2f19d691691de5a77bde', 'register', 1, 2, 1, '58.215.154.11', '中国', '浙江', '电信', 16340974537895, '2021-10-13 11:57:33', 6, 'docs->register', 'vip,docs,vip,register,docs,register,', 'vip'),
	(12, 1, '986af2288aba52b2217999d47815f161', 'index', 1, 1, 16, '58.215.154.11', '中国', '浙江', '电信', 16340974537947, '2021-10-13 11:57:33', 1, '开始->index', 'index,vip,docs_info,login,', 'index'),
	(13, 1, '986af2288aba52b2217999d47815f161', 'vip', 1, 1, 8, '58.215.154.11', '中国', '浙江', '电信', 16340974537964, '2021-10-13 11:57:33', 2, 'index->vip', 'index,vip,docs_info,login,', 'index'),
	(14, 1, '986af2288aba52b2217999d47815f161', 'docs_info', 1, 10, 13, '58.215.154.11', '中国', '浙江', '电信', 16340974537988, '2021-10-13 11:57:33', 3, 'vip->docs_info', 'index,vip,docs_info,login,', 'index'),
	(15, 1, '986af2288aba52b2217999d47815f161', 'login', 1, 4, 14, '58.215.154.11', '中国', '浙江', '电信', 16340974538001, '2021-10-13 11:57:33', 4, 'docs_info->login', 'index,vip,docs_info,login,', 'index'),
	(16, 1, '507d9499211c9824a8695f7435a7ac10', 'vip', 1, 7, 6, '58.215.154.11', '中国', '浙江', '电信', 16340974538030, '2021-10-13 11:57:33', 1, '开始->vip', 'vip,docs,vip,', 'vip'),
	(17, 1, '507d9499211c9824a8695f7435a7ac10', 'docs', 2, 9, 11, '58.215.154.11', '中国', '浙江', '电信', 16340974538063, '2021-10-13 11:57:33', 2, 'vip->docs', 'vip,docs,vip,', 'vip'),
	(18, 1, '507d9499211c9824a8695f7435a7ac10', 'vip', 1, 8, 14, '58.215.154.11', '中国', '浙江', '电信', 16340974538093, '2021-10-13 11:57:33', 3, 'docs->vip', 'vip,docs,vip,', 'vip'),
	(19, 1, 'da12a40893595407063c5624886785e1', 'login', 1, 8, 13, '58.215.154.11', '中国', '浙江', '电信', 16340974538126, '2021-10-13 11:57:33', 1, '开始->login', 'login,index,', 'login'),
	(20, 1, 'da12a40893595407063c5624886785e1', 'index', 2, 6, 9, '58.215.154.11', '中国', '浙江', '电信', 16340974538142, '2021-10-13 11:57:33', 2, 'login->index', 'login,index,', 'login'),
	(21, 1, '78d274609307e36d247edeb4ff0990c1', 'index', 2, 5, 13, '58.215.154.11', '中国', '浙江', '电信', 16340974538187, '2021-10-13 11:57:33', 1, '开始->index', 'index,docs_info,login,', 'index'),
	(22, 1, '78d274609307e36d247edeb4ff0990c1', 'docs_info', 1, 7, 1, '58.215.154.11', '中国', '浙江', '电信', 16340974538211, '2021-10-13 11:57:33', 2, 'index->docs_info', 'index,docs_info,login,', 'index'),
	(23, 1, '78d274609307e36d247edeb4ff0990c1', 'login', 2, 10, 5, '58.215.154.11', '中国', '浙江', '电信', 16340974538231, '2021-10-13 11:57:33', 3, 'docs_info->login', 'index,docs_info,login,', 'index'),
	(24, 1, '7b55a7e47aa2a9bc3df78530c9f30b5b', 'docs_info', 2, 6, 5, '58.215.154.11', '中国', '浙江', '电信', 16340974538259, '2021-10-13 11:57:33', 1, '开始->docs_info', 'docs_info,vip,docs_info,login,register,', 'docs_info'),
	(25, 1, '7b55a7e47aa2a9bc3df78530c9f30b5b', 'vip', 1, 10, 8, '58.215.154.11', '中国', '浙江', '电信', 16340974538288, '2021-10-13 11:57:33', 2, 'docs_info->vip', 'docs_info,vip,docs_info,login,register,', 'docs_info'),
	(26, 1, '7b55a7e47aa2a9bc3df78530c9f30b5b', 'docs_info', 2, 1, 2, '58.215.154.11', '中国', '浙江', '电信', 16340974538307, '2021-10-13 11:57:33', 3, 'vip->docs_info', 'docs_info,vip,docs_info,login,register,', 'docs_info'),
	(27, 1, '7b55a7e47aa2a9bc3df78530c9f30b5b', 'login', 2, 1, 18, '58.215.154.11', '中国', '浙江', '电信', 16340974538328, '2021-10-13 11:57:33', 4, 'docs_info->login', 'docs_info,vip,docs_info,login,register,', 'docs_info'),
	(28, 1, '7b55a7e47aa2a9bc3df78530c9f30b5b', 'register', 2, 8, 11, '58.215.154.11', '中国', '浙江', '电信', 16340974538349, '2021-10-13 11:57:33', 5, 'login->register', 'docs_info,vip,docs_info,login,register,', 'docs_info'),
	(29, 1, '53e4594a9447fe84581094bd1875e4b9', 'login', 1, 6, 3, '58.215.154.11', '中国', '浙江', '电信', 16340974538373, '2021-10-13 11:57:33', 1, '开始->login', 'login,vip,docs_info,register,', 'login'),
	(30, 1, '53e4594a9447fe84581094bd1875e4b9', 'vip', 1, 2, 1, '58.215.154.11', '中国', '浙江', '电信', 16340974538406, '2021-10-13 11:57:33', 2, 'login->vip', 'login,vip,docs_info,register,', 'login'),
	(31, 1, '53e4594a9447fe84581094bd1875e4b9', 'docs_info', 1, 3, 12, '58.215.154.11', '中国', '浙江', '电信', 16340974538421, '2021-10-13 11:57:33', 3, 'vip->docs_info', 'login,vip,docs_info,register,', 'login'),
	(32, 1, '53e4594a9447fe84581094bd1875e4b9', 'register', 2, 9, 4, '58.215.154.11', '中国', '浙江', '电信', 16340974538457, '2021-10-13 11:57:33', 4, 'docs_info->register', 'login,vip,docs_info,register,', 'login'),
	(33, 1, 'b6097b46a490c99ceda1f9bde09d1edc', 'register', 2, 7, 6, '58.215.154.11', '中国', '浙江', '电信', 16340974538476, '2021-10-13 11:57:33', 1, '开始->register', 'register,docs,index,vip,index,', 'register'),
	(34, 1, 'b6097b46a490c99ceda1f9bde09d1edc', 'docs', 2, 9, 10, '58.215.154.11', '中国', '浙江', '电信', 16340974538521, '2021-10-13 11:57:33', 2, 'register->docs', 'register,docs,index,vip,index,', 'register'),
	(35, 1, 'b6097b46a490c99ceda1f9bde09d1edc', 'index', 2, 4, 12, '58.215.154.11', '中国', '浙江', '电信', 16340974538537, '2021-10-13 11:57:33', 3, 'docs->index', 'register,docs,index,vip,index,', 'register'),
	(36, 1, 'b6097b46a490c99ceda1f9bde09d1edc', 'vip', 2, 1, 10, '58.215.154.11', '中国', '浙江', '电信', 16340974538557, '2021-10-13 11:57:33', 4, 'index->vip', 'register,docs,index,vip,index,', 'register'),
	(37, 1, 'b6097b46a490c99ceda1f9bde09d1edc', 'index', 1, 1, 12, '58.215.154.11', '中国', '浙江', '电信', 16340974538606, '2021-10-13 11:57:33', 5, 'vip->index', 'register,docs,index,vip,index,', 'register');

golang代码

package main

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"io/ioutil"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

var mydb *gorm.DB

func main() {


	engine := gin.Default()
	engine.LoadHTMLGlob("html/*")
	engine.Static("/html", "/Users/java0904/goProject/user_path/html")
	engine.GET("/", func(context *gin.Context) {
		firstPage := context.Query("a")
		secondPage := context.Query("b")
		thridPage := context.Query("c")
		foruthPage := context.Query("d")
		fivePage := context.Query("e")
		start := context.Query("start")
		end := context.Query("end")
		fmt.Println("firstPage:", firstPage)
		fmt.Printf("firstPage:%s,secondPage:%s,thridPage:%s\n", firstPage, secondPage, thridPage)
		prewhere := " where 1=1 "
		where := ""
		if firstPage != "" {
			where = " and first_page='" + firstPage + "'"
		}
		if firstPage != "" && secondPage != "" {
			where = " and full_path like '" + firstPage + "," + secondPage + ",%'"
		}
		if firstPage != "" && secondPage != "" && thridPage != "" {
			where = " and full_path like '" + firstPage + "," + secondPage + "," + thridPage + ",%'"
		}
		if firstPage != "" && secondPage != "" && thridPage != "" && foruthPage != "" {
			where = " and full_path like '" + firstPage + "," + secondPage + "," + thridPage + "," + foruthPage + ",%'"
		}
		if firstPage != "" && secondPage != "" && thridPage != "" && foruthPage != "" && fivePage != "" {
			where = " and full_path like '" + firstPage + "," + secondPage + "," + thridPage + "," + foruthPage + "," + fivePage + ",%'"
		}
		if start != "" && end != "" {
			prewhere = prewhere + " and created_at between '" + start + "' and '" + end + "' "
		}
		where = prewhere + where
		ma := make(map[string]interface{})
		//每个页面的访问数量
		var a []map[string]interface{}
		mydb.Raw("select count(*) as total,page from log " + where + " group by page order by `page`").Scan(&a)
		ma["a"] = a

		//每个页面、每个步骤的访问数量
		var b []map[string]interface{}
		mydb.Raw("select count(*) as total,view_num,page from log " + where + " group by view_num,page order by `page`,view_num").Scan(&b)
		ma["b"] = b

		//所有页面的总访问次数
		c := make(map[string]interface{})
		mydb.Raw("select count(*) as total  from log " + where).Scan(&c)
		ma["c"] = c

		//每个页面的流失数量
		var d []map[string]interface{}
		//rand.Seed(time.Now().UnixNano())
		//tablename:=rand.Intn(10000000)+10000000
		//mydb.Exec("create table tmp"+strconv.Itoa(tablename)+" select a.* from log a inner join (select max(view_num) top,uuid  from log group by uuid) c on a.view_num=c.top and a.uuid=c.uuid")
		mydb.Raw("select count(*) as total, d.page from (select a.page, a.view_num from log a inner join ( select max(view_num) top,b.uuid from log b " + where + " group by uuid ) c on a.view_num = c.top  and a.uuid = c.uuid ) d group by d.page").Scan(&d)
		ma["d"] = d

		//每个路径的、每个步骤的访问数量
		var e []map[string]interface{}
		sql := "select count(*) total ,view_num,path from log " + where + " group by view_num,path order by view_num,path "
		fmt.Println(sql)
		mydb.Raw(sql).Scan(&e)
		ma["e"] = e

		var f [][]interface{}

		//获取桑基图的所有名称,即data节点,和links节点
		for _, value := range e {
			tmap := make(map[string]interface{})
			tmap["value"] = value["total"]
			split := strings.Split(value["path"].(string), "->")
			sourceitoa := strconv.Itoa(int(value["view_num"].(int64) - 1))
			targetitoa := strconv.Itoa(int(value["view_num"].(int64)))
			if sourceitoa == "0" {
				sourceitoa = ""
			}
			f = append(f, []interface{}{split[0] + sourceitoa, split[1] + targetitoa, value["total"]})
		}

		marshal, _ := json.Marshal(f)
		old := string(marshal)
		//old = strings.Replace(old, "\"", "'",-1)
		//old = strings.Replace(old, "[[", "[",-1)
		//old = strings.Replace(old, "]]", "]",-1)
		//写入文本
		//桑基图地址https://echarts.apache.org/examples/zh/editor.html?c=sankey-simple&lang=js
		ioutil.WriteFile("/Users/java0904/goProject/user_path/link.txt", []byte(old), 0666)
		ma["link"] = old
		context.HTML(200, "tongji.html", ma)
	})

	engine.GET("/sangji", func(context *gin.Context) {
		context.HTML(200, "sangji.html", nil)
	})
	engine.GET("/sangji.gif", func(context *gin.Context) {
		context.String(200,"ok",nil)
		//context.HTML(200, "sangji.html", nil)
	})
	//k := make(map[int]interface{})
	//for i := 1; i < 9; i++ {
	//	var mm []map[string]interface{}
	//	mydb.Raw("select * from tmp6 where view_num=?", i).Scan(&mm)
	//	k[i] = mm
	//}
	//marshal2, _ := json.Marshal(k)
	//ioutil.WriteFile("/Users/java0904/goProject/user_path/test3.txt", marshal2, 0666)

	engine.Run(":9090")

}

func init() {
	dsn := "root:root@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)

	}

	sqlDB, err := db.DB()
	mydb = db
	// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
	sqlDB.SetMaxIdleConns(10)

	// SetMaxOpenConns sets the maximum number of open connections to the database.
	sqlDB.SetMaxOpenConns(100)

	// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
	sqlDB.SetConnMaxLifetime(time.Hour)
}

// 模拟插入数据
func insertData() {
	pages := []string{"首页", "注册", "登录", "购买会员", "文档", "购买接口"}
	pages = pages
	users := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
		"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	uuids := []string{"1111111", "2222222", "333333", "444444", "5555555", "6666666", "7777777", "8888888", "9999999"}
	uuids = uuids
	rand.Seed(time.Now().UnixNano())
	for _, user := range users {
		fmt.Println(user, rand.Intn(5)+5)
		num := rand.Intn(5) + 5
		uuid := user + strconv.Itoa(int(time.Now().UnixNano()))
		for i := 0; i < num; i++ {
			page := pages[rand.Intn(len(pages))]
			mydb.Exec("insert into user_events_logs (`view_num`,`uuid`,`page`,username) values(?,?,?,?)", i+1, uuid, page, "用户"+user)
		}
	}
}

html

sangji.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <link rel="icon" href="https://static.jianshukeji.com/hcode/images/favicon.ico">
    <style>
        #container {
            min-width: 300px;
            max-width: 800px;
            height: 400px;
            margin: 0 auto;
            border: 1px solid silver;
        }

        .highcharts-credits {
            display: none;
        }
    </style>
    <script src="https://cdn.highcharts.com.cn/highcharts/highcharts.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/exporting.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/sankey.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/oldie.js"></script>
</head>
<body>
<!--
*************************************************************************
   Generated by JShare at 2021-10-13 18:01:35
   From: https://jshare.com.cn/public/O0Gjuj/1
*************************************************************************
 -->
<div id="container"></div>

<script>
    Highcharts.chart('container', {
        title: {
            text: 'Highcharts 桑基图'
        },
        series: [{
            keys: ['from', 'to', 'weight'],
            data: [

                ['开始','index1',3],['index1','docs_info2',3],['docs_info2','register3',3],['register3','vip4',3],['vip4','docs5',1],['vip4','register5',2],['docs5','register6',1],['register5','docs6',1],['docs6','vip7',1],['register6','index7',1],['index7','login8',1]


            ],
            type: 'sankey',
            name: 'Sankey demo series'
        }]
    });
</script>
</body>
</html>

tongji.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>采集得到API</title>
    <style>
        .right-nav {
            background-color: aliceblue;
        }
    </style>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        #container {
            min-width: 300px;
            max-width: 800px;
            height: 400px;
            margin: 0 auto;
            border: 1px solid silver;
        }

        .highcharts-credits {
            display: none;
        }
    </style>
    <script src="https://cdn.highcharts.com.cn/highcharts/highcharts.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/exporting.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/sankey.js"></script>
    <script src="https://cdn.highcharts.com.cn/highcharts/modules/oldie.js"></script>
    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <link rel="icon" href="https://static.jianshukeji.com/hcode/images/favicon.ico">

    <![endif]-->
</head>


<body>
<div id="container"></div>

<div class="container">

    <div class="center-block">
        <p class="bg-primary">页面数据统计</p>

    </div>

    <table class="table  table-striped">
        <caption class="text-warning bg-warning"><strong>页面总访问次数</strong></caption>
        <thead>
        <tr class="danger">
            <th>页面</th>
            <th>访问总数</th>
            <th>用户流失数</th>
        </tr>
        </thead>
        <tbody>
        {{$myd:=.d}}
        {{range $index, $v :=.a}}
        <tr>
            <td>{{$v.page}}</td>
            <td>{{$v.total}}</td>
            {{range $i,$vv:= $myd}}
            {{if eq $vv.page $v.page}}
            <td>{{$vv.total}}</td>
            {{else}}
            {{end}}
            {{end}}

        </tr>
        {{end}}
        <tr>
            <td>合计:</td>
            <td>{{.c.total}}</td>
        </tr>


        </tbody>
    </table>
    <hr>

    <table class="table  table-striped">
        <caption class="text-warning bg-warning"><strong>转化数</strong></caption>
        <thead>
        <tr class="danger">
            <th>步骤</th>
            <th>路径</th>
            <th>数量</th>
        </tr>
        </thead>
        <tbody>
        {{range $index, $v :=.e}}
        <tr>
            <td>{{$v.view_num}}</td>
            <td>{{$v.path}}</td>
            <td>{{$v.total}}</td>
        </tr>
        {{end}}



        </tbody>
    </table>
    <hr>
    <table class="table  table-striped">
        <caption class="text-warning bg-warning"><strong>访问次数说明</strong></caption>
        <thead>
        <tr class="danger">
            <th>页面</th>
            <th>第几次访问</th>
            <th>访问总数</th>
        </tr>
        </thead>
        <tbody>
        {{range $index, $v :=.b}}
        <tr>
            <td>{{$v.page}}</td>
            <td>{{$v.view_num}}</td>
            <td>{{$v.total}}</td>
        </tr>
        {{end}}
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        </tbody>
    </table>

</div>

<script >
    var links = {{.link}}
    var parse = JSON.parse(links);
    var ss = [{
        keys: ['from', 'to', 'weight'],
        data:
            parse
            // ['开始','index1',3],['index1','docs_info2',3],['docs_info2','register3',3],['register3','vip4',3],['vip4','docs5',1],['vip4','register5',2],['docs5','register6',1],['register5','docs6',1],['docs6','vip7',1],['register6','index7',1],['index7','login8',1]
        ,
        type: 'sankey',
        name: 'Sankey demo series'
    }]
    Highcharts.chart('container', {
        title: {
            text: 'Highcharts 桑基图'
        },
        series: ss
    });
</script>
</body>
</html>

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

micro_cloud_fly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值