From 962e93c73ece1dbb72ba26b8edbdbc71f6b40419 Mon Sep 17 00:00:00 2001 From: xiangheng <11675084@qq.com> Date: Thu, 7 Nov 2024 14:26:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=85=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/api/monitor/slow.ts | 77 ++++++ admin/src/main.ts | 7 +- admin/src/views/monitor/error/index.vue | 2 +- admin/src/views/monitor/slow/edit.vue | 158 ++++++++++++ admin/src/views/monitor/slow/index.vue | 201 ++++++++++++++++ server/admin/common/index/index.go | 8 - server/admin/common/index/service.go | 7 +- server/admin/monitor_slow/monitor_slow_ctl.go | 217 +++++++++++++++++ .../admin/monitor_slow/monitor_slow_schema.go | 63 +++++ .../monitor_slow/monitor_slow_service.go | 224 ++++++++++++++++++ server/core/null_float.go | 66 +++--- server/model/monitor_slow.go | 16 ++ server/router/admin/entry.go | 1 + server/router/admin/monitor_slow_route.go | 59 +++++ server/util/convert.go | 7 +- server/util/convert/convert.go | 104 ++++++++ server/util/ip.go | 3 +- x_err_sdk/web/err-entry.ts | 3 +- x_err_sdk/web/err-implement.ts | 1 + 19 files changed, 1171 insertions(+), 53 deletions(-) create mode 100644 admin/src/api/monitor/slow.ts create mode 100644 admin/src/views/monitor/slow/edit.vue create mode 100644 admin/src/views/monitor/slow/index.vue create mode 100644 server/admin/monitor_slow/monitor_slow_ctl.go create mode 100644 server/admin/monitor_slow/monitor_slow_schema.go create mode 100644 server/admin/monitor_slow/monitor_slow_service.go create mode 100644 server/model/monitor_slow.go create mode 100644 server/router/admin/monitor_slow_route.go create mode 100644 server/util/convert/convert.go diff --git a/admin/src/api/monitor/slow.ts b/admin/src/api/monitor/slow.ts new file mode 100644 index 0000000..3eb6fe7 --- /dev/null +++ b/admin/src/api/monitor/slow.ts @@ -0,0 +1,77 @@ +import request from '@/utils/request' +import type { Pages } from '@/utils/request' + +import config from '@/config' +import queryString from 'query-string' +import { getToken } from '@/utils/auth' +import { clearEmpty } from '@/utils/util' + +export type type_monitor_slow = { + Id?: number + ProjectKey?: string + ClientId?: string + UserId?: string + Path?: string + Time?: number + CreateTime?: string +} +// 查询 +export type type_monitor_slow_query = { + ProjectKey?: string + ClientId?: string + UserId?: string + Path?: string + Time?: number + CreateTimeStart?: string + CreateTimeEnd?: string +} +// 添加编辑 +export type type_monitor_slow_edit = { + Id?: number + ProjectKey?: string + ClientId?: string + UserId?: string + Path?: string + Time?: number +} + +// 监控-错误列列表 +export function monitor_slow_list(params?: type_monitor_slow_query) { + return request.get>({ url: '/monitor_slow/list', params: clearEmpty(params) }) +} +// 监控-错误列列表-所有 +export function monitor_slow_list_all(params?: type_monitor_slow_query) { + return request.get({ url: '/monitor_slow/listAll', params: clearEmpty(params) }) +} + +// 监控-错误列详情 +export function monitor_slow_detail(Id: number | string) { + return request.get({ url: '/monitor_slow/detail', params: { Id } }) +} + +// 监控-错误列新增 +export function monitor_slow_add(data: type_monitor_slow_edit) { + return request.post({ url: '/monitor_slow/add', data }) +} + +// 监控-错误列编辑 +export function monitor_slow_edit(data: type_monitor_slow_edit) { + return request.post({ url: '/monitor_slow/edit', data }) +} + +// 监控-错误列删除 +export function monitor_slow_delete(Id: number | string) { + return request.post({ url: '/monitor_slow/del', data: { Id } }) +} +// 监控-错误列删除-批量 +export function monitor_slow_delete_batch(data: { Ids: string }) { + return request.post({ url: '/monitor_slow/delBatch', data }) +} + +// 监控-错误列导入 +export const monitor_slow_import_file = '/monitor_slow/ImportFile' + +// 监控-错误列导出 +export function monitor_slow_export_file(params: any) { + return (window.location.href =`${config.baseUrl}${config.urlPrefix}/monitor_slow/ExportFile?token=${getToken()}&` + queryString.stringify(clearEmpty(params))) +} diff --git a/admin/src/main.ts b/admin/src/main.ts index c136afe..3f3103e 100644 --- a/admin/src/main.ts +++ b/admin/src/main.ts @@ -13,16 +13,17 @@ import VForm3 from 'vform3-builds' //引入VForm3库 import { XErr, XErrWeb } from '../../x_err_sdk/web/index' // { XErr, XErrWeb } -new XErr( +const xErr = new XErr( { - Dns: 'http://localhost:5174/api', + Dns: `${location.origin}/api`, Pid: 'e19e3be20de94f49b68fafb4c30668bc', - Uid: '10' + Uid: '' }, new XErrWeb({ onloadTimeOut: 3000 }) ) +xErr.SetUid(1) //设置用户ID const app = createApp(App) app.use(install) diff --git a/admin/src/views/monitor/error/index.vue b/admin/src/views/monitor/error/index.vue index 4a27059..34ae969 100644 --- a/admin/src/views/monitor/error/index.vue +++ b/admin/src/views/monitor/error/index.vue @@ -66,7 +66,7 @@ /> - + diff --git a/admin/src/views/monitor/slow/edit.vue b/admin/src/views/monitor/slow/edit.vue new file mode 100644 index 0000000..1a50708 --- /dev/null +++ b/admin/src/views/monitor/slow/edit.vue @@ -0,0 +1,158 @@ + + diff --git a/admin/src/views/monitor/slow/index.vue b/admin/src/views/monitor/slow/index.vue new file mode 100644 index 0000000..a904924 --- /dev/null +++ b/admin/src/views/monitor/slow/index.vue @@ -0,0 +1,201 @@ + + diff --git a/server/admin/common/index/index.go b/server/admin/common/index/index.go index 71992cf..238b918 100644 --- a/server/admin/common/index/index.go +++ b/server/admin/common/index/index.go @@ -8,14 +8,6 @@ import ( ) func IndexRoute(rg *gin.RouterGroup) { - // db := core.GetDB() - // permSrv := system.NewSystemAuthPermService(db) - // roleSrv := system.NewSystemAuthRoleService(db, permSrv) - // adminSrv := system.NewSystemAuthAdminService(db, permSrv, roleSrv) - // service := system.NewSystemLoginService(db, adminSrv) - - // authSrv := system.NewSystemAuthMenuService(db, permSrv) - // IndexService := NewIndexService() handle := indexHandler{} rg = rg.Group("/common", middleware.TokenAuth()) diff --git a/server/admin/common/index/service.go b/server/admin/common/index/service.go index 6e49404..097f954 100644 --- a/server/admin/common/index/service.go +++ b/server/admin/common/index/service.go @@ -10,15 +10,10 @@ import ( "gorm.io/gorm" ) -type IIndexService interface { - Console() (res map[string]interface{}, e error) - Config() (res map[string]interface{}, e error) -} - var Service = NewIndexService() // NewIndexService 初始化 -func NewIndexService() IIndexService { +func NewIndexService() *indexService { db := core.GetDB() return &indexService{db: db} } diff --git a/server/admin/monitor_slow/monitor_slow_ctl.go b/server/admin/monitor_slow/monitor_slow_ctl.go new file mode 100644 index 0000000..2d98d84 --- /dev/null +++ b/server/admin/monitor_slow/monitor_slow_ctl.go @@ -0,0 +1,217 @@ +package monitor_slow + +import ( + "net/http" + "strconv" + "strings" + "time" + "github.com/gin-gonic/gin" + "x_admin/core/request" + "x_admin/core/response" + "x_admin/util" + "x_admin/util/excel2" + "golang.org/x/sync/singleflight" +) + + +type MonitorSlowHandler struct { + requestGroup singleflight.Group +} + +// @Summary 监控-错误列列表 +// @Tags monitor_slow-监控-错误列 +// @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 Path query string false "URL地址" +// @Param Time query number false "时间" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +//@Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorSlowResp}} "成功" +//@Router /api/admin/monitor_slow/list [get] +func (hd *MonitorSlowHandler) List(c *gin.Context) { + var page request.PageReq + var listReq MonitorSlowListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) { + return + } + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := MonitorSlowService.List(page, listReq) + response.CheckAndRespWithData(c, res, err) +} + +// @Summary 监控-错误列列表-所有 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Param ProjectKey query string false "项目key" +// @Param ClientId query string false "sdk生成的客户端id" +// @Param UserId query string false "用户id" +// @Param Path query string false "URL地址" +// @Param Time query number false "时间" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Success 200 {object} response.Response{ data=[]MonitorSlowResp} "成功" +// @Router /api/admin/monitor_slow/listAll [get] +func (hd *MonitorSlowHandler) ListAll(c *gin.Context) { + var listReq MonitorSlowListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := MonitorSlowService.ListAll(listReq) + response.CheckAndRespWithData(c, res, err) +} + +// @Summary 监控-错误列详情 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Param Token header string true "token" +// @Param Id query number false "错误id" +// @Success 200 {object} response.Response{ data=MonitorSlowResp} "成功" +// @Router /api/admin/monitor_slow/detail [get] +func (hd *MonitorSlowHandler) Detail(c *gin.Context) { + var detailReq MonitorSlowDetailReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) { + return + } + res, err, _ := hd.requestGroup.Do("MonitorSlow:Detail:"+strconv.Itoa(detailReq.Id), func() (any, error) { + v, err := MonitorSlowService.Detail(detailReq.Id) + return v, err + }) + + response.CheckAndRespWithData(c, res, err) +} + + +// @Summary 监控-错误列新增 +// @Tags monitor_slow-监控-错误列 +// @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 Path body string false "URL地址" +// @Param Time body number false "时间" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_slow/add [post] +func (hd *MonitorSlowHandler) Add(c *gin.Context) { + var addReq MonitorSlowAddReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { + return + } + createId, e := MonitorSlowService.Add(addReq) + response.CheckAndRespWithData(c,createId, e) +} +// @Summary 监控-错误列编辑 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Param Token header string true "token" +// @Param Id body number false "错误id" +// @Param ProjectKey body string false "项目key" +// @Param ClientId body string false "sdk生成的客户端id" +// @Param UserId body string false "用户id" +// @Param Path body string false "URL地址" +// @Param Time body number false "时间" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_slow/edit [post] +func (hd *MonitorSlowHandler) Edit(c *gin.Context) { + var editReq MonitorSlowEditReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) { + return + } + response.CheckAndRespWithData(c,editReq.Id, MonitorSlowService.Edit(editReq)) +} +// @Summary 监控-错误列删除 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Param Token header string true "token" +// @Param Id body number false "错误id" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_slow/del [post] +func (hd *MonitorSlowHandler) Del(c *gin.Context) { + var delReq MonitorSlowDelReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { + return + } + response.CheckAndResp(c, MonitorSlowService.Del(delReq.Id)) +} + +// @Summary 监控-错误列删除-批量 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Param Token header string true "token" +// @Param Ids body string false "逗号分割的id" +// @Success 200 {object} response.Response "成功" +// @Router /api/admin/monitor_slow/delBatch [post] +func (hd *MonitorSlowHandler) DelBatch(c *gin.Context) { + var delReq MonitorSlowDelBatchReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { + return + } + if delReq.Ids == "" { + response.FailWithMsg(c, response.SystemError, "请选择要删除的数据") + return + } + var Ids = strings.Split(delReq.Ids, ",") + + response.CheckAndResp(c, MonitorSlowService.DelBatch(Ids)) +} + + + +// @Summary 监控-错误列导出 +// @Tags monitor_slow-监控-错误列 +// @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 Path query string false "URL地址" +// @Param Time query number false "时间" +// @Param CreateTimeStart query string false "创建时间" +// @Param CreateTimeEnd query string false "创建时间" +// @Router /api/admin/monitor_slow/ExportFile [get] +func (hd *MonitorSlowHandler) ExportFile(c *gin.Context) { + var listReq MonitorSlowListReq + if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { + return + } + res, err := MonitorSlowService.ExportFile(listReq) + if err != nil { + response.FailWithMsg(c, response.SystemError, "查询信息失败") + return + } + f, err := excel2.Export(res,MonitorSlowService.GetExcelCol(), "Sheet1", "监控-错误列") + if err != nil { + response.FailWithMsg(c, response.SystemError, "导出失败") + return + } + excel2.DownLoadExcel("监控-错误列" + time.Now().Format("20060102-150405"), c.Writer, f) +} + +// @Summary 监控-错误列导入 +// @Tags monitor_slow-监控-错误列 +// @Produce json +// @Router /api/admin/monitor_slow/ImportFile [post] +func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) { + file, _, err := c.Request.FormFile("file") + if err != nil { + c.String(http.StatusInternalServerError, "文件不存在") + return + } + defer file.Close() + importList := []MonitorSlowResp{} + err = excel2.GetExcelData(file, &importList,MonitorSlowService.GetExcelCol()) + if err != nil { + c.String(http.StatusInternalServerError, err.Error()) + return + } + + err = MonitorSlowService.ImportFile(importList) + response.CheckAndResp(c, err) +} \ No newline at end of file diff --git a/server/admin/monitor_slow/monitor_slow_schema.go b/server/admin/monitor_slow/monitor_slow_schema.go new file mode 100644 index 0000000..72ec211 --- /dev/null +++ b/server/admin/monitor_slow/monitor_slow_schema.go @@ -0,0 +1,63 @@ +package monitor_slow +import ( + "x_admin/core" + +) + +//MonitorSlowListReq 监控-错误列列表参数 +type MonitorSlowListReq struct { + ProjectKey *string // 项目key + ClientId *string // sdk生成的客户端id + UserId *string // 用户id + Path *string // URL地址 + Time *float64 // 时间 + CreateTimeStart *string // 开始创建时间 + CreateTimeEnd *string // 结束创建时间 +} + + + +//MonitorSlowAddReq 监控-错误列新增参数 +type MonitorSlowAddReq struct { + ProjectKey *string // 项目key + ClientId *string // sdk生成的客户端id + UserId *string // 用户id + Path *string // URL地址 + Time core.NullFloat // 时间 +} + +//MonitorSlowEditReq 监控-错误列编辑参数 +type MonitorSlowEditReq struct { + Id int // 错误id + ProjectKey *string // 项目key + ClientId *string // sdk生成的客户端id + UserId *string // 用户id + Path *string // URL地址 + Time core.NullFloat // 时间 +} + +//MonitorSlowDetailReq 监控-错误列详情参数 +type MonitorSlowDetailReq struct { + Id int // 错误id +} + +//MonitorSlowDelReq 监控-错误列删除参数 +type MonitorSlowDelReq struct { + Id int // 错误id +} + +//MonitorSlowDelReq 监控-错误列批量删除参数 +type MonitorSlowDelBatchReq struct { + Ids string +} + +//MonitorSlowResp 监控-错误列返回信息 +type MonitorSlowResp struct { + Id int // 错误id + ProjectKey string // 项目key + ClientId string // sdk生成的客户端id + UserId string // 用户id + Path string // URL地址 + Time core.NullFloat // 时间 + CreateTime core.NullTime // 创建时间 +} diff --git a/server/admin/monitor_slow/monitor_slow_service.go b/server/admin/monitor_slow/monitor_slow_service.go new file mode 100644 index 0000000..5b3dda8 --- /dev/null +++ b/server/admin/monitor_slow/monitor_slow_service.go @@ -0,0 +1,224 @@ +package monitor_slow + +import ( + "x_admin/core" + "x_admin/core/request" + "x_admin/core/response" + "x_admin/model" + "gorm.io/gorm" + "x_admin/util" + "x_admin/util/excel2" +) + +var MonitorSlowService=NewMonitorSlowService() +var cacheUtil = util.CacheUtil{ + Name: MonitorSlowService.Name, +} + +// NewMonitorSlowService 初始化 +func NewMonitorSlowService() *monitorSlowService { + return &monitorSlowService{ + db: core.GetDB(), + Name: "monitorSlow", + } +} + +//monitorSlowService 监控-错误列服务实现类 +type monitorSlowService struct { + db *gorm.DB + Name string +} + + + +// List 监控-错误列列表 +func (service monitorSlowService) GetModel(listReq MonitorSlowListReq) *gorm.DB { + // 查询 + dbModel := service.db.Model(&model.MonitorSlow{}) + if listReq.ProjectKey!= nil { + dbModel = dbModel.Where("project_key = ?", *listReq.ProjectKey) + } + if listReq.ClientId!= nil { + dbModel = dbModel.Where("client_id = ?", *listReq.ClientId) + } + if listReq.UserId!= nil { + dbModel = dbModel.Where("user_id = ?", *listReq.UserId) + } + if listReq.Path!= nil { + dbModel = dbModel.Where("path = ?", *listReq.Path) + } + if listReq.Time!= nil { + dbModel = dbModel.Where("time = ?", *listReq.Time) + } + if listReq.CreateTimeStart!= nil { + dbModel = dbModel.Where("create_time >= ?", *listReq.CreateTimeStart) + } + if listReq.CreateTimeEnd!= nil { + dbModel = dbModel.Where("create_time <= ?", *listReq.CreateTimeEnd) + } + return dbModel +} +// List 监控-错误列列表 +func (service monitorSlowService) List(page request.PageReq, listReq MonitorSlowListReq) (res response.PageResp, e error) { + // 分页信息 + limit := page.PageSize + offset := page.PageSize * (page.PageNo - 1) + dbModel := service.GetModel(listReq) + // 总数 + var count int64 + err := dbModel.Count(&count).Error + if e = response.CheckErr(err, "失败"); e != nil { + return + } + // 数据 + var modelList []model.MonitorSlow + err = dbModel.Limit(limit).Offset(offset).Order("id desc").Find(&modelList).Error + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + result := []MonitorSlowResp{} + util.ConvertUtil.Copy(&result, modelList) + return response.PageResp{ + PageNo: page.PageNo, + PageSize: page.PageSize, + Count: count, + Lists: result, + }, nil +} +// ListAll 监控-错误列列表 +func (service monitorSlowService) ListAll(listReq MonitorSlowListReq) (res []MonitorSlowResp, e error) { + dbModel := service.GetModel(listReq) + + var modelList []model.MonitorSlow + + err := dbModel.Find(&modelList).Error + if e = response.CheckErr(err, "查询全部失败"); e != nil { + return + } + util.ConvertUtil.Copy(&res, modelList) + return res, nil +} + +// Detail 监控-错误列详情 +func (service monitorSlowService) Detail(Id int) (res MonitorSlowResp, e error) { + var obj = model.MonitorSlow{} + err := cacheUtil.GetCache(Id, &obj) + if err != nil { + err := service.db.Where("id = ?", Id).Limit(1).First(&obj).Error + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "获取详情失败"); e != nil { + return + } + cacheUtil.SetCache(obj.Id, obj) + } + + util.ConvertUtil.Copy(&res, obj) + return +} + +// Add 监控-错误列新增 +func (service monitorSlowService) Add(addReq MonitorSlowAddReq) (createId int,e error) { + var obj model.MonitorSlow + util.ConvertUtil.StructToStruct(addReq,&obj) + err := service.db.Create(&obj).Error + e = response.CheckMysqlErr(err) + if e != nil { + return 0,e + } + cacheUtil.SetCache(obj.Id, obj) + createId = obj.Id + return +} + +// Edit 监控-错误列编辑 +func (service monitorSlowService) Edit(editReq MonitorSlowEditReq) (e error) { + var obj model.MonitorSlow + err := service.db.Where("id = ?", editReq.Id).Limit(1).First(&obj).Error + // 校验 + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + util.ConvertUtil.Copy(&obj, editReq) + + err = service.db.Model(&obj).Select("*").Updates(obj).Error + if e = response.CheckErr(err, "编辑失败"); e != nil { + return + } + cacheUtil.RemoveCache(obj.Id) + service.Detail(obj.Id) + return +} + +// Del 监控-错误列删除 +func (service monitorSlowService) Del(Id int) (e error) { + var obj model.MonitorSlow + err := service.db.Where("id = ?", Id).Limit(1).First(&obj).Error + // 校验 + if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { + return + } + if e = response.CheckErr(err, "查询数据失败"); e != nil { + return + } + // 删除 + err = service.db.Delete(&obj).Error + e = response.CheckErr(err, "删除失败") + cacheUtil.RemoveCache(obj.Id) + return +} + +// DelBatch 用户协议-批量删除 +func (service monitorSlowService) DelBatch(Ids []string) (e error) { + var obj model.MonitorSlow + err := service.db.Where("id in (?)", Ids).Delete(&obj).Error + if err != nil { + return err + } + // 删除缓存 + cacheUtil.RemoveCache(Ids) + return nil +} + +// 获取Excel的列 +func (service monitorSlowService) GetExcelCol() []excel2.Col { + var cols = []excel2.Col{ + {Name: "项目key", Key: "ProjectKey", Width: 15}, + {Name: "sdk生成的客户端id", Key: "ClientId", Width: 15}, + {Name: "用户id", Key: "UserId", Width: 15}, + {Name: "URL地址", Key: "Path", Width: 15}, + {Name: "时间", Key: "Time", Width: 15}, + {Name: "创建时间", Key: "CreateTime", Width: 15, Decode: util.NullTimeUtil.DecodeTime }, + } + // 还可以考虑字典,请求下来加上 Replace 实现替换导出 + return cols +} + +// ExportFile 监控-错误列导出 +func (service monitorSlowService) ExportFile(listReq MonitorSlowListReq) (res []MonitorSlowResp, e error) { + // 查询 + dbModel := service.GetModel(listReq) + + // 数据 + var modelList []model.MonitorSlow + err := dbModel.Order("id asc").Find(&modelList).Error + if e = response.CheckErr(err, "查询失败"); e != nil { + return + } + result := []MonitorSlowResp{} + util.ConvertUtil.Copy(&result, modelList) + return result, nil +} + +// 导入 +func (service monitorSlowService) ImportFile(importReq []MonitorSlowResp) (e error) { + var importData []model.MonitorSlow + util.ConvertUtil.Copy(&importData, importReq) + err := service.db.Create(&importData).Error + e = response.CheckErr(err, "添加失败") + return e +} \ No newline at end of file diff --git a/server/core/null_float.go b/server/core/null_float.go index 749c410..efeb73e 100644 --- a/server/core/null_float.go +++ b/server/core/null_float.go @@ -4,6 +4,7 @@ import ( "database/sql/driver" "encoding/json" "strconv" + "x_admin/util/convert" ) // Float类型别名,支持前端传递null,float64, string类型 @@ -13,35 +14,14 @@ type NullFloat struct { Valid bool } -// func EncodeFloat(value any) any { -// switch v := value.(type) { -// case map[string]any: -// if v["Float"] != nil { -// val := v["Float"] -// switch f := val.(type) { -// case *float32: -// return float64(*f) -// case *float64: -// return *f -// case *int: -// return float64(*f) -// case *int64: -// return float64(*f) -// case *string: -// return *f -// default: -// return nil -// } -// } -// } -// return nil -// } - func DecodeFloat(value any) (any, error) { switch v := value.(type) { case float64: f := v return NullFloat{Float: &f, Valid: true}, nil + case float32: + f := float64(v) + return NullFloat{Float: &f, Valid: true}, nil case int: f := float64(v) return NullFloat{Float: &f, Valid: true}, nil @@ -65,12 +45,42 @@ func DecodeFloat(value any) (any, error) { // gorm实现Scanner func (f *NullFloat) Scan(value interface{}) error { f.Valid = false - if value == nil { - return nil + + result, err := convert.ConvertUtil.ToFloat64(value) + if err != nil { + return err } - v := value.(float64) - f.Float, f.Valid = &v, true + f.Float, f.Valid = &result, true return nil + // switch v := value.(type) { + // case float64: + // f.Float, f.Valid = &v, true + // case float32: + // // 直接用float64(float32(v)), 会丢失精度 + // val, _ := strconv.ParseFloat(fmt.Sprintf("%f", v), 64) + // f.Float, f.Valid = &val, true + // // 匹配所有int + // case uint, uint8, uint16, uint32, uint64, int8, int16, int, int32, int64: + // val := float64(v) + // f.Float, f.Valid = &val, true + // case string: + // if v == "" { + // f.Float, f.Valid = nil, false + // return nil + // } + // val, err := strconv.ParseFloat(v, 64) + // if err != nil { + // f.Float, f.Valid = nil, false + // return err + // } + // f.Float, f.Valid = &val, true + // return err + // case nil: + // f.Float, f.Valid = nil, false + // return nil + // } + + // return nil } // gorm实现 Valuer diff --git a/server/model/monitor_slow.go b/server/model/monitor_slow.go new file mode 100644 index 0000000..72b0d37 --- /dev/null +++ b/server/model/monitor_slow.go @@ -0,0 +1,16 @@ +package model + +import ( + "x_admin/core" +) + +// MonitorSlow 监控-错误列实体 +type MonitorSlow struct { + Id int `gorm:"primarykey;comment:'错误id'"` // 错误id + ProjectKey string `gorm:"comment:'项目key'"` // 项目key + ClientId string `gorm:"comment:'sdk生成的客户端id'"` // sdk生成的客户端id + UserId string `gorm:"comment:'用户id'"` // 用户id + Path string `gorm:"comment:'URL地址'"` // URL地址 + Time core.NullFloat `gorm:"comment:'时间'"` // 时间 + CreateTime core.NullTime `gorm:"autoCreateTime;comment:'创建时间'"` // 创建时间 +} diff --git a/server/router/admin/entry.go b/server/router/admin/entry.go index 6245a0e..3e8da09 100644 --- a/server/router/admin/entry.go +++ b/server/router/admin/entry.go @@ -60,6 +60,7 @@ func RegisterGroup(rg *gin.RouterGroup) { MonitorProjectRoute(rg) MonitorClientRoute(rg) MonitorErrorRoute(rg) + MonitorSlowRoute(rg) UserProtocolRoute(rg) } diff --git a/server/router/admin/monitor_slow_route.go b/server/router/admin/monitor_slow_route.go new file mode 100644 index 0000000..a62dee5 --- /dev/null +++ b/server/router/admin/monitor_slow_route.go @@ -0,0 +1,59 @@ +package admin + +import ( + "x_admin/admin/monitor_slow" + "x_admin/middleware" + + "github.com/gin-gonic/gin" +) + +/** +集成 +1. 导入 +- 请先提交git避免文件覆盖!!! +- 下载并解压压缩包后,直接复制server、admin文件夹到项目根目录即可 + +2. 注册路由 +请在 router/admin/entry.go 文件引入 MonitorSlowRoute 注册路由 + +3. 后台手动添加菜单和按钮 +admin:monitor_slow:add +admin:monitor_slow:edit +admin:monitor_slow:del +admin:monitor_slow:delBatch +admin:monitor_slow:list +admin:monitor_slow:listAll +admin:monitor_slow:detail +admin:monitor_slow:ExportFile +admin:monitor_slow:ImportFile + +// 列表-先添加菜单获取菜单id +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, paths, component, is_cache, is_show, is_disable, create_time, update_time) VALUES (0, 'C', '慢接口', 'monitor/slow/index', 'monitor/slow/index', 0, 1, 0, now(), now()); +按钮-替换pid参数为菜单id + +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口添加','admin:monitor_slow:add', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口编辑','admin:monitor_slow:edit', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口删除','admin:monitor_slow:del', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口删除-批量','admin:monitor_slow:delBatch', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口列表','admin:monitor_slow:list', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口全部列表','admin:monitor_slow:listAll', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口详情','admin:monitor_slow:detail', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口导出excel','admin:monitor_slow:ExportFile', 0, 1, 0, now(), now()); +INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_show, is_disable, create_time, update_time) VALUES (834, 'A', '慢接口导入excel','admin:monitor_slow:ImportFile', 0, 1, 0, now(), now()); +*/ + +// MonitorSlowRoute(rg) +func MonitorSlowRoute(rg *gin.RouterGroup) { + handle := monitor_slow.MonitorSlowHandler{} + rg.POST("/monitor_slow/add", middleware.RecordLog("慢接口新增"), handle.Add) + r := rg.Group("/", middleware.TokenAuth()) + r.GET("/monitor_slow/list", handle.List) + r.GET("/monitor_slow/listAll", handle.ListAll) + r.GET("/monitor_slow/detail", handle.Detail) + + r.POST("/monitor_slow/del", middleware.RecordLog("慢接口删除"), handle.Del) + r.POST("/monitor_slow/delBatch", middleware.RecordLog("慢接口删除-批量"), handle.DelBatch) + + r.GET("/monitor_slow/ExportFile", middleware.RecordLog("慢接口导出"), handle.ExportFile) + // r.POST("/monitor_slow/ImportFile", handle.ImportFile) +} diff --git a/server/util/convert.go b/server/util/convert.go index 8e84e5b..85186a7 100644 --- a/server/util/convert.go +++ b/server/util/convert.go @@ -2,7 +2,6 @@ package util import ( "reflect" - "x_admin/core" "github.com/fatih/structs" "github.com/jinzhu/copier" @@ -28,7 +27,7 @@ func (c convertUtil) StructsToMaps(from interface{}) (data []map[string]interfac var objList []interface{} err := copier.Copy(&objList, from) if err != nil { - core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) + // core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) return nil } for _, v := range objList { @@ -57,7 +56,7 @@ func (c convertUtil) ShallowStructsToMaps(from interface{}) (data []map[string]i var objList []interface{} err := copier.Copy(&objList, from) if err != nil { - core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) + // core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) return nil } for _, v := range objList { @@ -82,7 +81,7 @@ func (c convertUtil) StructToStruct(from interface{}, to interface{}) (err error func (c convertUtil) Copy(toValue interface{}, fromValue interface{}) interface{} { if err := copier.Copy(toValue, fromValue); err != nil { - core.Logger.Errorf("Copy err: err=[%+v]", err) + // core.Logger.Errorf("Copy err: err=[%+v]", err) panic("SystemError") } return toValue diff --git a/server/util/convert/convert.go b/server/util/convert/convert.go new file mode 100644 index 0000000..1171f1d --- /dev/null +++ b/server/util/convert/convert.go @@ -0,0 +1,104 @@ +package convert + +import ( + "fmt" + "strconv" + + "reflect" + + "github.com/duke-git/lancet/v2/convertor" + + "github.com/fatih/structs" + "github.com/jinzhu/copier" + "github.com/mitchellh/mapstructure" +) + +var ConvertUtil = convertUtil{} + +// convertUtil 转换工具 +type convertUtil struct{} + +func (c convertUtil) ToFloat64(value interface{}) (float64, error) { + switch v := value.(type) { + case float64, float32: + return strconv.ParseFloat(fmt.Sprintf("%f", v), 64) + default: + return convertor.ToFloat(value) + } + + // return 0, nil +} + +// StructToMap 结构体转换成map,深度转换 +func (c convertUtil) StructToMap(from interface{}) map[string]interface{} { + // var m = map[string]interface{}{} + // mapstructure.Decode(from, &m) //深度转换所有结构体 + + m := structs.Map(from) // 需要tag:structs,深度转换 + return m +} + +// StructsToMaps 将结构体转换成Map列表 +func (c convertUtil) StructsToMaps(from interface{}) (data []map[string]interface{}) { + var objList []interface{} + err := copier.Copy(&objList, from) + if err != nil { + // core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) + return nil + } + for _, v := range objList { + data = append(data, c.StructToMap(v)) + } + return data +} + +// ShallowStructToMap 将结构体转换成map,浅转换 +func (c convertUtil) ShallowStructToMap(from interface{}) map[string]interface{} { + m := make(map[string]interface{}) + v := reflect.ValueOf(from) + t := v.Type() + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + value := v.Field(i).Interface() + m[field.Name] = value + } + + return m +} + +// ShallowStructsToMaps 将结构体列表转换成Map列表,浅转换 +func (c convertUtil) ShallowStructsToMaps(from interface{}) (data []map[string]interface{}) { + var objList []interface{} + err := copier.Copy(&objList, from) + if err != nil { + // core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err) + return nil + } + for _, v := range objList { + data = append(data, c.ShallowStructToMap(v)) + } + return data +} + +// MapToStruct 将map弱类型转换成结构体 +func (c convertUtil) MapToStruct(from interface{}, to interface{}) (err error) { + err = mapstructure.WeakDecode(from, to) // 需要tag:mapstructure + return err +} + +// StructToStruct 将结构体from弱类型转换成结构体to +func (c convertUtil) StructToStruct(from interface{}, to interface{}) (err error) { + m := c.StructToMap(from) + err = c.MapToStruct(m, to) + + return err +} + +func (c convertUtil) Copy(toValue interface{}, fromValue interface{}) interface{} { + if err := copier.Copy(toValue, fromValue); err != nil { + // core.Logger.Errorf("Copy err: err=[%+v]", err) + panic("SystemError") + } + return toValue +} diff --git a/server/util/ip.go b/server/util/ip.go index fc74196..75d8548 100644 --- a/server/util/ip.go +++ b/server/util/ip.go @@ -4,7 +4,6 @@ import ( "fmt" "net" "strings" - "x_admin/core" "github.com/lionsoul2014/ip2region/binding/golang/xdb" ) @@ -20,7 +19,7 @@ type ipUtil struct { func (su ipUtil) GetHostIp() (ip string) { conn, err := net.Dial("udp", "114.114.114.114:80") if err != nil { - core.Logger.Errorf("GetHostIp Dial err: err=[%+v]", err) + // core.Logger.Errorf("GetHostIp Dial err: err=[%+v]", err) return } defer conn.Close() diff --git a/x_err_sdk/web/err-entry.ts b/x_err_sdk/web/err-entry.ts index 56438a0..53e48d5 100644 --- a/x_err_sdk/web/err-entry.ts +++ b/x_err_sdk/web/err-entry.ts @@ -59,8 +59,9 @@ class XLog { // 设置用户id public SetUid(uid?: Uid) { if (uid) { - this.platform?.setCache("x_err_uid", uid); this.Uid = uid; + this.platform?.setCache("x_err_uid", uid); + } else { const u_id = this.platform?.getCache("x_err_uid"); if (u_id) { diff --git a/x_err_sdk/web/err-implement.ts b/x_err_sdk/web/err-implement.ts index ab8cb76..d6feca0 100644 --- a/x_err_sdk/web/err-implement.ts +++ b/x_err_sdk/web/err-implement.ts @@ -193,6 +193,7 @@ class Logger implements IErrorEvent { }); } } + }; public listen(callback: ListenCallbackFn): void { this.callback = callback;