业务场景
今天给自己的项目加了几个echarts图表,主要用以显示我的几个系统的近一周访问量,大概是这个样子
三个图标分别是:我的简历访问量,我的音乐访问量,简历和音乐访问量对比
1.数据采集
这个访问信息的采集是在我的简历和我的音乐页面提交信息,也就是个很简单的接口,提交用户访问该页面的时间和页面类型(简历页面或者是音乐页面)
2,数据整理
把近一周时间内每天的访问量整理出来返回给前端系统
// 获取我的音乐本周访问量
func (this Personal) GetMusicData(ctx *gin.Context) {
now := time.Now()
year, month, day := now.Date()
// 今天的时间
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
//今天的时间-1
t1 := today.AddDate(0, 0, -1)
//今天的时间-2
t2 := today.AddDate(0, 0, -2)
//今天的时间-3
t3 := today.AddDate(0, 0, -3)
//今天的时间-4
t4 := today.AddDate(0, 0, -4)
//今天的时间-5
t5 := today.AddDate(0, 0, -5)
//今天的时间-6
t6 := today.AddDate(0, 0, -6)
tourist1 := []modules.Tourist{}
tourist2 := []modules.Tourist{}
tourist3 := []modules.Tourist{}
tourist4 := []modules.Tourist{}
tourist5 := []modules.Tourist{}
tourist6 := []modules.Tourist{}
tourist7 := []modules.Tourist{}
err := modules.DB.Where("scene LIKE ? AND add_time > ?", "%music%", today).Find(&tourist1).Error
err2 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t1, today).Find(&tourist2).Error
err3 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t2, t1).Find(&tourist3).Error
err4 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t3, t2).Find(&tourist4).Error
err5 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t4, t3).Find(&tourist4).Error
err6 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t5, t4).Find(&tourist4).Error
err7 := modules.DB.Where("scene LIKE ? AND add_time > ? AND add_time < ?", "%music%", t6, t5).Find(&tourist4).Error
if err != nil || err2 != nil || err3 != nil || err4 != nil || err5 != nil || err6 != nil || err7 != nil {
ctx.JSON(400, gin.H{
"message": "获取失败",
})
} else {
arr := []int{len(tourist7), len(tourist6), len(tourist5), len(tourist4), len(tourist3), len(tourist2), len(tourist1)}
ctx.JSON(200, gin.H{
"message": "获取成功",
"data": arr,
})
}
}
这是整理音乐页面访问量的函数,简历页面同理
3,前端获取到数据后把数据绑定给echarts图标
... ...
此处省略前端代码若干行
4,重点部分:使用websocket和服务端生成长链接,访问量变化了实时通知前端获取最新数据
后端部分
"github.com/gorilla/websocket"
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
//这里声明一个链接池
var conns []*websocket.Conn
func (this UserController) WS(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
println("upgrade错误:", err)
return
}
defer c.Close()
//把所有链接存在链接池里
conns = append(conns, c)
for {
_, _, err := c.ReadMessage()
if err != nil {
println("read:", err)
break
}
}
}
在数据采集到函数里,当收到有人访问那两个页面,把链接池里的链接都通知一遍
func (this UserController) AddTourist(ctx *gin.Context) {
scene := ctx.Request.FormValue("scene")
message := ctx.Request.FormValue("message")
time := time.Now().UTC()
tourist := &modules.Tourist{
Scene: scene,
Message: message,
AddTime: time,
}
err := modules.DB.Model(&modules.Tourist{}).Create(&tourist).Error
if err != nil {
ctx.JSON(400, gin.H{
"message": "新增浏览用户信息失败",
})
} else {
//这里是重点,循环链接池,广播消息,消息类型随便定,只要你前端知道就行,我这里通知一个数字1
for i := range conns {
if index := strings.Index(scene, "jianli"); index != -1 {
conns[i].WriteMessage(websocket.TextMessage, []byte("jianli"))
} else if index := strings.Index(scene, "music"); index != -1 {
conns[i].WriteMessage(websocket.TextMessage, []byte("music"))
}
}
ctx.JSON(200, gin.H{
"message": "新增浏览用户信息成功!",
})
}
}
然后是管理系统收到推送的消息,重新刷新数据,这样就实现了数据随访问量实时变化的功能
const websocket=new WebSocket("ws://xxx.xxx.xxx.xxx:8088/ws")
websocket.onopen=(evt)=>{
console.log("链接成功")
}
websocket.onmessage=(evt)=>{
//收到后端推送的消息,刷新对应数据
if(evt.data=="jianli"){
refreshChartJL()
}else if(evt.data=="music"){
refreshChartMusic()
}
}
websocket.onclose=()=>{
console.log("链接关闭")
}
const getAllData=()=>{
...
...
...
}
总结:这个功能实现下来,也并不难,但一定要动手实现一下,如果你有啥疑问,可以留言,我每天都能看到