diff --git a/server/admin/monitor_client/monitor_client_ctl.go b/server/admin/monitor_client/monitor_client_ctl.go index c0e67c7..25d6e84 100644 --- a/server/admin/monitor_client/monitor_client_ctl.go +++ b/server/admin/monitor_client/monitor_client_ctl.go @@ -1,10 +1,12 @@ package monitor_client import ( + "fmt" "net/http" "strconv" "strings" "time" + "x_admin/core" "x_admin/core/request" "x_admin/core/response" "x_admin/util" @@ -18,26 +20,26 @@ type MonitorClientHandler struct { requestGroup singleflight.Group } -// @Summary 监控-客户端信息列表 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param PageNo query int true "页码" -// @Param PageSize query int true "每页数量" -// @Param ProjectKey query string false "项目key" -// @Param ClientId query string false "sdk生成的客户端id" -// @Param UserId query string false "用户id" -// @Param Os query string false "系统" -// @Param Browser query string false "浏览器" -// @Param City query string false "城市" -// @Param Width query number false "屏幕" -// @Param Height query number false "屏幕高度" -// @Param Ua query string false "ua记录" -// @Param CreateTimeStart query string false "创建时间" -// @Param CreateTimeEnd query string false "创建时间" +// @Summary 监控-客户端信息列表 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param Token header string true "token" +// @Param PageNo query int true "页码" +// @Param PageSize query int true "每页数量" +// @Param ProjectKey query string false "项目key" +// @Param ClientId query string false "sdk生成的客户端id" +// @Param UserId query string false "用户id" +// @Param Os query string false "系统" +// @Param Browser query string false "浏览器" +// @Param City query string false "城市" +// @Param Width query number false "屏幕" +// @Param Height query number false "屏幕高度" +// @Param Ua query string false "ua记录" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" // -// @Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorClientResp}} "成功" -// @Router /api/admin/monitor_client/list [get] +// @Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorClientResp}} "成功" +// @Router /api/admin/monitor_client/list [get] func (hd *MonitorClientHandler) List(c *gin.Context) { var page request.PageReq var listReq MonitorClientListReq @@ -51,22 +53,22 @@ func (hd *MonitorClientHandler) List(c *gin.Context) { response.CheckAndRespWithData(c, res, err) } -// @Summary 监控-客户端信息列表-所有 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param ProjectKey query string false "项目key" -// @Param ClientId query string false "sdk生成的客户端id" -// @Param UserId query string false "用户id" -// @Param Os query string false "系统" -// @Param Browser query string false "浏览器" -// @Param City query string false "城市" -// @Param Width query number false "屏幕" -// @Param Height query number false "屏幕高度" -// @Param Ua query string false "ua记录" -// @Param CreateTimeStart query string false "创建时间" -// @Param CreateTimeEnd query string false "创建时间" -// @Success 200 {object} response.Response{ data=[]MonitorClientResp} "成功" -// @Router /api/admin/monitor_client/listAll [get] +// @Summary 监控-客户端信息列表-所有 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param ProjectKey query string false "项目key" +// @Param ClientId query string false "sdk生成的客户端id" +// @Param UserId query string false "用户id" +// @Param Os query string false "系统" +// @Param Browser query string false "浏览器" +// @Param City query string false "城市" +// @Param Width query number false "屏幕" +// @Param Height query number false "屏幕高度" +// @Param Ua query string false "ua记录" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Success 200 {object} response.Response{ data=[]MonitorClientResp} "成功" +// @Router /api/admin/monitor_client/listAll [get] func (hd *MonitorClientHandler) ListAll(c *gin.Context) { var listReq MonitorClientListReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { @@ -85,13 +87,13 @@ func (hd *MonitorClientHandler) ErrorUsers(c *gin.Context) { response.CheckAndRespWithData(c, res, err) } -// @Summary 监控-客户端信息详情 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param Id query number false "uuid" -// @Success 200 {object} response.Response{ data=MonitorClientResp} "成功" -// @Router /api/admin/monitor_client/detail [get] +// @Summary 监控-客户端信息详情 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param Token header string true "token" +// @Param Id query number false "uuid" +// @Success 200 {object} response.Response{ data=MonitorClientResp} "成功" +// @Router /api/admin/monitor_client/detail [get] func (hd *MonitorClientHandler) Detail(c *gin.Context) { var detailReq MonitorClientDetailReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) { @@ -105,61 +107,49 @@ func (hd *MonitorClientHandler) Detail(c *gin.Context) { response.CheckAndRespWithData(c, res, err) } -// @Summary 监控-客户端信息新增 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param ProjectKey body string false "项目key" -// @Param ClientId body string false "sdk生成的客户端id" -// @Param UserId body string false "用户id" -// @Param Os body string false "系统" -// @Param Browser body string false "浏览器" -// @Param City body string false "城市" -// @Param Width body number false "屏幕" -// @Param Height body number false "屏幕高度" -// @Param Ua body string false "ua记录" -// @Success 200 {object} response.Response "成功" -// @Router /api/admin/monitor_client/add [post] +// @Summary 监控-客户端信息新增 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param Token header string true "token" +// @Param ProjectKey body string false "项目key" +// @Param ClientId body string false "sdk生成的客户端id" +// @Param UserId body string false "用户id" +// @Param Os body string false "系统" +// @Param Browser body string false "浏览器" +// @Param City body string false "城市" +// @Param Width body number false "屏幕" +// @Param Height body number false "屏幕高度" +// @Param Ua body string false "ua记录" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_client/add [post] func (hd *MonitorClientHandler) Add(c *gin.Context) { + var addReq MonitorClientAddReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { return } + uaStr := c.GetHeader("user-agent") + ua := core.UAParser.Parse(uaStr) + fmt.Println("ua", ua.Device.Family) + addReq.Ua = &uaStr + addReq.Os = &ua.Os.Family + addReq.Browser = &ua.UserAgent.Family + // addReq.Ip = *c.ClientIP() + core.IpUtils.Parse(c.ClientIP()) + core.IpUtils.Parse("124.223.171.170") + core.IpUtils.Parse("118.24.157.190") + createId, e := MonitorClientService.Add(addReq) response.CheckAndRespWithData(c, createId, e) } -// @Summary 监控-客户端信息编辑 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param Id body number false "uuid" -// @Param ProjectKey body string false "项目key" -// @Param ClientId body string false "sdk生成的客户端id" -// @Param UserId body string false "用户id" -// @Param Os body string false "系统" -// @Param Browser body string false "浏览器" -// @Param City body string false "城市" -// @Param Width body number false "屏幕" -// @Param Height body number false "屏幕高度" -// @Param Ua body string false "ua记录" -// @Success 200 {object} response.Response "成功" -// @Router /api/admin/monitor_client/edit [post] -// func (hd *MonitorClientHandler) Edit(c *gin.Context) { -// var editReq MonitorClientEditReq -// if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) { -// return -// } -// response.CheckAndRespWithData(c, editReq.Id, MonitorClientService.Edit(editReq)) -// } - -// @Summary 监控-客户端信息删除 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param Id body number false "uuid" -// @Success 200 {object} response.Response "成功" -// @Router /api/admin/monitor_client/del [post] +// @Summary 监控-客户端信息删除 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param Token header string true "token" +// @Param Id body number false "uuid" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_client/del [post] func (hd *MonitorClientHandler) Del(c *gin.Context) { var delReq MonitorClientDelReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { @@ -168,14 +158,14 @@ func (hd *MonitorClientHandler) Del(c *gin.Context) { response.CheckAndResp(c, MonitorClientService.Del(delReq.Id)) } -// @Summary 监控-客户端信息删除-批量 -// @Tags monitor_client-监控-客户端信息 +// @Summary 监控-客户端信息删除-批量 +// @Tags monitor_client-监控-客户端信息 // -// @Produce json -// @Param Token header string true "token" -// @Param Ids body string false "逗号分割的id" -// @Success 200 {object} response.Response "成功" -// @Router /api/admin/monitor_client/delBatch [post] +// @Produce json +// @Param Token header string true "token" +// @Param Ids body string false "逗号分割的id" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_client/delBatch [post] func (hd *MonitorClientHandler) DelBatch(c *gin.Context) { var delReq MonitorClientDelBatchReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { @@ -190,22 +180,22 @@ func (hd *MonitorClientHandler) DelBatch(c *gin.Context) { response.CheckAndResp(c, MonitorClientService.DelBatch(Ids)) } -// @Summary 监控-客户端信息导出 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Param Token header string true "token" -// @Param ProjectKey query string false "项目key" -// @Param ClientId query string false "sdk生成的客户端id" -// @Param UserId query string false "用户id" -// @Param Os query string false "系统" -// @Param Browser query string false "浏览器" -// @Param City query string false "城市" -// @Param Width query number false "屏幕" -// @Param Height query number false "屏幕高度" -// @Param Ua query string false "ua记录" -// @Param CreateTimeStart query string false "创建时间" -// @Param CreateTimeEnd query string false "创建时间" -// @Router /api/admin/monitor_client/ExportFile [get] +// @Summary 监控-客户端信息导出 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Param Token header string true "token" +// @Param ProjectKey query string false "项目key" +// @Param ClientId query string false "sdk生成的客户端id" +// @Param UserId query string false "用户id" +// @Param Os query string false "系统" +// @Param Browser query string false "浏览器" +// @Param City query string false "城市" +// @Param Width query number false "屏幕" +// @Param Height query number false "屏幕高度" +// @Param Ua query string false "ua记录" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Router /api/admin/monitor_client/ExportFile [get] func (hd *MonitorClientHandler) ExportFile(c *gin.Context) { var listReq MonitorClientListReq if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { @@ -224,10 +214,10 @@ func (hd *MonitorClientHandler) ExportFile(c *gin.Context) { excel2.DownLoadExcel("监控-客户端信息"+time.Now().Format("20060102-150405"), c.Writer, f) } -// @Summary 监控-客户端信息导入 -// @Tags monitor_client-监控-客户端信息 -// @Produce json -// @Router /api/admin/monitor_client/ImportFile [post] +// @Summary 监控-客户端信息导入 +// @Tags monitor_client-监控-客户端信息 +// @Produce json +// @Router /api/admin/monitor_client/ImportFile [post] func (hd *MonitorClientHandler) ImportFile(c *gin.Context) { file, _, err := c.Request.FormFile("file") if err != nil { diff --git a/server/core/ip.go b/server/core/ip.go new file mode 100644 index 0000000..b050785 --- /dev/null +++ b/server/core/ip.go @@ -0,0 +1,82 @@ +package core + +import ( + "fmt" + "strings" + + "github.com/lionsoul2014/ip2region/binding/golang/xdb" +) + +var IpUtils = new(ipUtils) + +type ipUtils struct { + Searcher *xdb.Searcher +} + +func init() { + var dbPath = "resources/ip/ip2region.xdb" + // 创建完全基于内存的查询对象。 + cBuff, err := xdb.LoadContentFromFile(dbPath) + if err != nil { + fmt.Printf("failed to load content from `%s`: %s\n", dbPath, err) + return + } + // 并发使用,用整个 xdb 缓存创建的 searcher 对象可以安全用于并发。 + searcher, err := xdb.NewWithBuffer(cBuff) + + if err != nil { + fmt.Printf("failed to create searcher: %s\n", err.Error()) + return + } + fmt.Printf("创建完全基于内存的查询对象。") + IpUtils.Searcher = searcher + // defer searcher.Close() + + // region, err := searcher.SearchByStr(ip) + // if err != nil { + // fmt.Printf("failed to SearchIP(%s): %s\n", ip, err) + // return + // } + // fmt.Printf("{region: %+v}\n", region) +} + +type Region struct { + Country string + Province string + City string + Operator string +} + +func (ipUtils *ipUtils) Parse(ip string) Region { + // var dbPath = "resources/ip/ip2region.xdb" + // // 创建完全基于内存的查询对象。 + // cBuff, err := xdb.LoadContentFromFile(dbPath) + // searcher, err := xdb.NewWithBuffer(cBuff) + + // if err != nil { + // fmt.Printf("failed to create searcher: %s\n", err.Error()) + // return + // } + // defer searcher.Close() + if ip == "" { + fmt.Println("输入ip为空") + return Region{} + } + region, err := ipUtils.Searcher.SearchByStr(ip) + if err != nil { + fmt.Printf("解析ip(%s)错误: %s\n", ip, err) + return Region{} + } + // 中国|0|四川省|成都市|电信 + parts := strings.Split(region, "|") + if len(parts) != 5 { + fmt.Println("解析ip返回错误") + return Region{} + } + country := parts[0] + province := parts[2] + city := parts[3] + operator := parts[4] + regionInfo := Region{Country: country, Province: province, City: city, Operator: operator} + return regionInfo +} diff --git a/server/go.mod b/server/go.mod index 0c3aacb..20ee082 100644 --- a/server/go.mod +++ b/server/go.mod @@ -65,9 +65,11 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/server/go.sum b/server/go.sum index 6d67b56..8577513 100644 --- a/server/go.sum +++ b/server/go.sum @@ -114,6 +114,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 h1:YeIGErDiB/fhmNsJy0cfjoT8XnRNT9hb19xZ4MvWQDU= +github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -125,6 +127,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA= github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/server/resources/ip/ip2region.xdb b/server/resources/ip/ip2region.xdb new file mode 100644 index 0000000..7052c05 Binary files /dev/null and b/server/resources/ip/ip2region.xdb differ