发布于2026-07-06 阅读(0)
扫一扫,手机访问
给自己的项目加几个 ECharts 图表,用来展示几个系统近一周的访问量。效果差不多是这样:

三个图表分别对应:简历访问量、音乐访问量、以及两者的对比
访问信息的采集入口很简单——在简历页面和音乐页面埋了一个提交接口,每次用户访问就上报页面类型和访问时间。不需要什么花哨的东西,一个接口搞定。
后端需要把近一周每天的数据按天汇总,然后返回给前端。来看一下音乐页面访问量的处理函数(简历页面同理):
// 获取我的音乐本周访问量
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)
t1 := today.AddDate(0, 0, -1)
t2 := today.AddDate(0, 0, -2)
t3 := today.AddDate(0, 0, -3)
t4 := today.AddDate(0, 0, -4)
t5 := today.AddDate(0, 0, -5)
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,
})
}
}
逻辑挺直白的:从今天往前推7天,每天分别查数据库里 scene 包含 "music" 的记录,最后按时间顺序打包成一个数组返回。
... ... 前端那部分没什么好展开的,无非是把拿到的数据塞进 ECharts 的 series 里,这里省略若干行。
访问量变化了,怎么能让页面自动刷新?老老实实让用户手动刷新肯定不现实,所以得靠 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 {
// 循环链接池,广播消息,消息类型随便定,前端认得就行
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=()=>{
...
...
...
}
整个实现下来其实并不复杂,核心就是 WebSocket 链路维护 + 数据采集时的广播通知。但别光看,动手写一遍才能真正吃透。如果你在实现过程中遇到什么问题,欢迎留言交流。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8