diff --git a/src/modules/network_data/controller/amf.go b/src/modules/network_data/controller/amf.go index 51cc8fbb..02bbed35 100644 --- a/src/modules/network_data/controller/amf.go +++ b/src/modules/network_data/controller/amf.go @@ -8,7 +8,6 @@ import ( "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" "be.ems/src/framework/utils/parse" - "be.ems/src/modules/network_data/model" neDataService "be.ems/src/modules/network_data/service" neFetchlink "be.ems/src/modules/network_element/fetch_link" neService "be.ems/src/modules/network_element/service" @@ -19,15 +18,15 @@ import ( // 实例化控制层 AMFController 结构体 var NewAMF = &AMFController{ neInfoService: neService.NewNeInfo, - ueEventService: neDataService.NewUEEventAMF, + ueEventService: neDataService.NewUEEvent, } // 网元AMF // // PATH /amf type AMFController struct { - neInfoService *neService.NeInfo // 网元信息服务 - ueEventService *neDataService.UEEventAMF // UE会话事件服务 + neInfoService *neService.NeInfo // 网元信息服务 + ueEventService *neDataService.UEEvent // UE会话事件服务 } // UE会话列表 @@ -49,23 +48,20 @@ type AMFController struct { // @Router /neData/amf/ue/list [get] func (s *AMFController) UEList(c *gin.Context) { language := reqctx.AcceptLanguage(c) - var querys model.UEEventAMFQuery - if err := c.ShouldBindQuery(&querys); err != nil { - errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) - return + query := reqctx.QueryMap(c) + // 限制导出数据集 + pageSize := parse.Number(query["pageSize"]) + if pageSize > 10000 { + query["pageSize"] = "10000" } - - // 查询网元获取IP - neInfo := s.neInfoService.FindByNeTypeAndNeID("AMF", querys.NeID) - if neInfo.NeId != querys.NeID || neInfo.IP == "" { + // 查询网元信息 rmUID + neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"]) + if neInfo.NeType == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - querys.RmUID = neInfo.RmUID - - // 查询数据 - rows, total := s.ueEventService.FindByPage(querys) + query["rmUID"] = neInfo.RmUID + rows, total := s.ueEventService.FindByPage(neInfo.NeType, query) c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) } @@ -98,7 +94,7 @@ func (s *AMFController) UERemove(c *gin.Context) { ids = append(ids, parse.Number(v)) } - rows, err := s.ueEventService.DeleteByIds(ids) + rows, err := s.ueEventService.DeleteByIds("AMF", ids) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return @@ -109,7 +105,7 @@ func (s *AMFController) UERemove(c *gin.Context) { // UE会话列表导出 // -// POST /ue/export +// GET /ue/export // // @Tags network_data/amf // @Accept json @@ -119,28 +115,23 @@ func (s *AMFController) UERemove(c *gin.Context) { // @Security TokenAuth // @Summary UE Session List Export // @Description UE Session List Export -// @Router /neData/amf/ue/export [post] +// @Router /neData/amf/ue/export [get] func (s *AMFController) UEExport(c *gin.Context) { language := reqctx.AcceptLanguage(c) - // 查询结果,根据查询条件结果,单页最大值限制 - var querys model.UEEventAMFQuery - if err := c.ShouldBindBodyWithJSON(&querys); err != nil { - errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) - return - } + query := reqctx.QueryMap(c) // 限制导出数据集 - if querys.PageSize > 10000 { - querys.PageSize = 10000 + pageSize := parse.Number(query["pageSize"]) + if pageSize > 10000 { + query["pageSize"] = "10000" } - // 查询网元获取IP - neInfo := s.neInfoService.FindByNeTypeAndNeID("AMF", querys.NeID) - if neInfo.NeId != querys.NeID || neInfo.IP == "" { + // 查询网元信息 rmUID + neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"]) + if neInfo.NeType == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - querys.RmUID = neInfo.RmUID - rows, total := s.ueEventService.FindByPage(querys) + query["rmUID"] = neInfo.RmUID + rows, total := s.ueEventService.FindByPage(neInfo.NeType, query) if total == 0 { // 导出数据记录为空 c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty"))) @@ -150,7 +141,7 @@ func (s *AMFController) UEExport(c *gin.Context) { // 导出文件名称 fileName := fmt.Sprintf("amf_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli()) // 导出数据表格 - saveFilePath, err := s.ueEventService.ExportXlsx(rows, fileName, language) + saveFilePath, err := s.ueEventService.ExportAMF(rows, fileName, language) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return diff --git a/src/modules/network_data/controller/mme.go b/src/modules/network_data/controller/mme.go index a64e15da..057689ab 100644 --- a/src/modules/network_data/controller/mme.go +++ b/src/modules/network_data/controller/mme.go @@ -8,7 +8,6 @@ import ( "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" "be.ems/src/framework/utils/parse" - "be.ems/src/modules/network_data/model" neDataService "be.ems/src/modules/network_data/service" neFetchlink "be.ems/src/modules/network_element/fetch_link" neService "be.ems/src/modules/network_element/service" @@ -19,15 +18,15 @@ import ( // 实例化控制层 MMEController 结构体 var NewMME = &MMEController{ neInfoService: neService.NewNeInfo, - ueEventService: neDataService.NewUEEventMME, + ueEventService: neDataService.NewUEEvent, } // 网元MME // // PATH /mme type MMEController struct { - neInfoService *neService.NeInfo // 网元信息服务 - ueEventService *neDataService.UEEventMME // UE会话事件服务 + neInfoService *neService.NeInfo // 网元信息服务 + ueEventService *neDataService.UEEvent // UE会话事件服务 } // UE会话列表 @@ -49,23 +48,20 @@ type MMEController struct { // @Router /neData/mme/ue/list [get] func (s *MMEController) UEList(c *gin.Context) { language := reqctx.AcceptLanguage(c) - var querys model.UEEventMMEQuery - if err := c.ShouldBindQuery(&querys); err != nil { - errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) - return + query := reqctx.QueryMap(c) + // 限制导出数据集 + pageSize := parse.Number(query["pageSize"]) + if pageSize > 10000 { + query["pageSize"] = "10000" } - - // 查询网元获取IP - neInfo := s.neInfoService.FindByNeTypeAndNeID("MME", querys.NeID) - if neInfo.NeId != querys.NeID || neInfo.IP == "" { + // 查询网元信息 rmUID + neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"]) + if neInfo.NeType == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - querys.RmUID = neInfo.RmUID - - // 查询数据 - rows, total := s.ueEventService.FindByPage(querys) + query["rmUID"] = neInfo.RmUID + rows, total := s.ueEventService.FindByPage(neInfo.NeType, query) c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) } @@ -98,7 +94,7 @@ func (s *MMEController) UERemove(c *gin.Context) { ids = append(ids, parse.Number(v)) } - rows, err := s.ueEventService.DeleteByIds(ids) + rows, err := s.ueEventService.DeleteByIds("MME", ids) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return @@ -109,7 +105,7 @@ func (s *MMEController) UERemove(c *gin.Context) { // UE会话列表导出 // -// POST /ue/export +// GET /ue/export // // @Tags network_data/mme // @Accept json @@ -119,28 +115,23 @@ func (s *MMEController) UERemove(c *gin.Context) { // @Security TokenAuth // @Summary UE Session List Export // @Description UE Session List Export -// @Router /neData/mme/ue/export [post] +// @Router /neData/mme/ue/export [get] func (s *MMEController) UEExport(c *gin.Context) { language := reqctx.AcceptLanguage(c) - // 查询结果,根据查询条件结果,单页最大值限制 - var querys model.UEEventMMEQuery - if err := c.ShouldBindBodyWithJSON(&querys); err != nil { - errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) - return - } + query := reqctx.QueryMap(c) // 限制导出数据集 - if querys.PageSize > 10000 { - querys.PageSize = 10000 + pageSize := parse.Number(query["pageSize"]) + if pageSize > 10000 { + query["pageSize"] = "10000" } - // 查询网元获取IP - neInfo := s.neInfoService.FindByNeTypeAndNeID("MME", querys.NeID) - if neInfo.NeId != querys.NeID || neInfo.IP == "" { + // 查询网元信息 rmUID + neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"]) + if neInfo.NeType == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - querys.RmUID = neInfo.RmUID - rows, total := s.ueEventService.FindByPage(querys) + query["rmUID"] = neInfo.RmUID + rows, total := s.ueEventService.FindByPage(neInfo.NeType, query) if total == 0 { // 导出数据记录为空 c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty"))) @@ -150,7 +141,7 @@ func (s *MMEController) UEExport(c *gin.Context) { // 导出文件名称 fileName := fmt.Sprintf("mme_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli()) // 导出数据表格 - saveFilePath, err := s.ueEventService.ExportXlsx(rows, fileName, language) + saveFilePath, err := s.ueEventService.ExportMME(rows, fileName, language) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return diff --git a/src/modules/network_data/model/ue_event.go b/src/modules/network_data/model/ue_event.go new file mode 100644 index 00000000..5b0b309d --- /dev/null +++ b/src/modules/network_data/model/ue_event.go @@ -0,0 +1,18 @@ +package model + +// UEEvent UE会话对象 ue_event +type UEEvent struct { + ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` + NeType string `json:"neType" gorm:"column:ne_type"` + NeName string `json:"neName" gorm:"column:ne_name"` + RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有 + Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到时间 + EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 + EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String + CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒 +} + +// TableName 表名称 +func (*UEEvent) TableName() string { + return "ue_event" +} diff --git a/src/modules/network_data/model/ue_event_amf.go b/src/modules/network_data/model/ue_event_amf.go deleted file mode 100644 index 23340324..00000000 --- a/src/modules/network_data/model/ue_event_amf.go +++ /dev/null @@ -1,33 +0,0 @@ -package model - -// UEEventAMF UE会话对象AMF ue_event_amf -type UEEventAMF struct { - ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` - NeType string `json:"neType" gorm:"column:ne_type"` - NeName string `json:"neName" gorm:"column:ne_name"` - RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有 - Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳 - EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state - EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String - CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒 -} - -// TableName 表名称 -func (*UEEventAMF) TableName() string { - return "ue_event_amf" -} - -// UEEventAMFQuery UE会话对象AMF查询参数结构体 -type UEEventAMFQuery struct { - NeType string `json:"neType" form:"neType" binding:"required,oneof=AMF"` // 网元类型, 暂时支持AMF - NeID string `json:"neId" form:"neId" binding:"required"` - RmUID string `json:"rmUID" form:"rmUID"` - EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state - IMSI string `json:"imsi" form:"imsi"` // imsi - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp - EndTime int64 `json:"endTime" form:"endTime"` - SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段 - SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc - PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"` - PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"` -} diff --git a/src/modules/network_data/model/ue_event_mme.go b/src/modules/network_data/model/ue_event_mme.go deleted file mode 100644 index 5c43eb79..00000000 --- a/src/modules/network_data/model/ue_event_mme.go +++ /dev/null @@ -1,33 +0,0 @@ -package model - -// UEEventMME UE会话对象MME ue_event_mme -type UEEventMME struct { - ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` - NeType string `json:"neType" gorm:"column:ne_type"` - NeName string `json:"neName" gorm:"column:ne_name"` - RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有 - Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳 - EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state - EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String - CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒 -} - -// TableName 表名称 -func (*UEEventMME) TableName() string { - return "ue_event_mme" -} - -// UEEventMMEQuery UE会话对象MME查询参数结构体 -type UEEventMMEQuery struct { - NeType string `json:"neType" form:"neType" binding:"required,oneof=MME"` // 网元类型, 暂时支持MME - NeID string `json:"neId" form:"neId" binding:"required"` - RmUID string `json:"rmUID" form:"rmUID"` - EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state - IMSI string `json:"imsi" form:"imsi"` // imsi - BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp - EndTime int64 `json:"endTime" form:"endTime"` - SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段 - SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc - PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"` - PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"` -} diff --git a/src/modules/network_data/repository/ue_event.go b/src/modules/network_data/repository/ue_event.go new file mode 100644 index 00000000..d06730f7 --- /dev/null +++ b/src/modules/network_data/repository/ue_event.go @@ -0,0 +1,132 @@ +package repository + +import ( + "fmt" + "strings" + "time" + + "be.ems/src/framework/database/db" + "be.ems/src/framework/logger" + "be.ems/src/modules/network_data/model" +) + +// 实例化数据层 UEEvent 结构体 +var NewUEEvent = &UEEvent{} + +// UEEvent UE会话事件 数据层处理 +type UEEvent struct{} + +// SelectByPage 分页查询集合 +func (r UEEvent) SelectByPage(neType string, query map[string]string) ([]model.UEEvent, int64) { + // 表名 + tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType)) + tx := db.DB("").Table(tableName).Model(&model.CDREvent{}) + // 查询条件拼接 + if v, ok := query["rmUID"]; ok && v != "" { + tx = tx.Where("rm_uid = ?", v) + } + if v, ok := query["beginTime"]; ok && v != "" { + if len(v) == 10 { + v = v + "000" + } + tx = tx.Where("timestamp >= ?", v) + } + if v, ok := query["endTime"]; ok && v != "" { + if len(v) == 10 { + v = v + "000" + } + tx = tx.Where("timestamp <= ?", v) + } + if v, ok := query["eventType"]; ok && v != "" { + eventTypes := strings.Split(v, ",") + tx = tx.Where("event_type in ?", eventTypes) + } + if v, ok := query["imsi"]; ok && v != "" { + tx = tx.Where("JSON_EXTRACT(event_json, '$.imsi') = ?", v) + } + + // 查询结果 + var total int64 = 0 + rows := []model.UEEvent{} + + // 查询数量 长度为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total + } + + // 分页 + pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"]) + tx = tx.Offset(int(pageNum * pageSize)).Limit(int(pageSize)) + + // 排序 + if v, ok := query["sortField"]; ok && v != "" { + sortSql := v + if o, ok := query["sortOrder"]; ok && o != "" { + if o == "desc" { + sortSql += " desc " + } else { + sortSql += " asc " + } + } + tx = tx.Order(sortSql) + } + + // 查询数据 + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query err => %v", err) + } + + return rows, total +} + +// SelectByIds 通过ID查询 +func (r UEEvent) SelectByIds(neType string, ids []int64) []model.UEEvent { + rows := []model.UEEvent{} + if len(ids) <= 0 { + return rows + } + // 表名 + tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType)) + tx := db.DB("").Table(tableName).Model(&model.UEEvent{}) + // 构建查询条件 + tx = tx.Where("id in ?", ids) + // 查询数据 + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows + } + return rows +} + +// DeleteByIds 批量删除信息 +func (r UEEvent) DeleteByIds(neType string, ids []int64) int64 { + if len(ids) <= 0 { + return 0 + } + // 表名 + tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType)) + tx := db.DB("").Table(tableName).Where("id in ?", ids) + if err := tx.Delete(&model.UEEvent{}).Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} + +// Insert 新增信息 返回新增数据ID +func (r UEEvent) Insert(param model.UEEvent) int64 { + if param.NeType == "" { + return 0 + } + if param.CreatedAt == 0 { + param.CreatedAt = time.Now().UnixMilli() + } + // 表名 + tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(param.NeType)) + // 执行插入 + if err := db.DB("").Table(tableName).Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) + return 0 + } + return param.ID +} diff --git a/src/modules/network_data/repository/ue_event_amf.go b/src/modules/network_data/repository/ue_event_amf.go deleted file mode 100644 index 60c109cc..00000000 --- a/src/modules/network_data/repository/ue_event_amf.go +++ /dev/null @@ -1,98 +0,0 @@ -package repository - -import ( - "strings" - - "be.ems/src/framework/database/db" - "be.ems/src/framework/logger" - "be.ems/src/modules/network_data/model" -) - -// 实例化数据层 UEEventAMF 结构体 -var NewUEEventAMF = &UEEventAMF{} - -// UEEventAMF UE会话事件 数据层处理 -type UEEventAMF struct{} - -// SelectByPage 分页查询集合 -func (r UEEventAMF) SelectByPage(query model.UEEventAMFQuery) ([]model.UEEventAMF, int64) { - tx := db.DB("").Model(&model.UEEventAMF{}) - // 查询条件拼接 - if query.NeType != "" { - tx = tx.Where("ne_type = ?", query.NeType) - } - if query.RmUID != "" { - tx = tx.Where("rm_uid = ?", query.RmUID) - } - if query.BeginTime != 0 { - tx = tx.Where("timestamp >= ?", query.BeginTime) - } - if query.EndTime != 0 { - tx = tx.Where("timestamp <= ?", query.EndTime) - } - if query.EventType != "" { - eventTypes := strings.Split(query.EventType, ",") - tx = tx.Where("event_type in ?", eventTypes) - } - if query.IMSI != "" { - tx = tx.Where("JSON_EXTRACT(event_json, '$.imsi') = ?", query.IMSI) - } - - // 查询结果 - var total int64 = 0 - rows := []model.UEEventAMF{} - - // 查询数量为0直接返回 - if err := tx.Count(&total).Error; err != nil || total <= 0 { - return rows, total - } - - // 排序 - if query.SortField != "" { - sortField := query.SortField - if query.SortOrder == "desc" { - sortField = sortField + " desc" - } - tx = tx.Order(sortField) - } - - // 查询数据分页 - pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize) - tx = tx.Limit(pageSize).Offset(pageSize * pageNum) - err := tx.Find(&rows).Error - if err != nil { - logger.Errorf("query find err => %v", err.Error()) - return rows, total - } - return rows, total -} - -// SelectByIds 通过ID查询 -func (r UEEventAMF) SelectByIds(ids []int64) []model.UEEventAMF { - rows := []model.UEEventAMF{} - if len(ids) <= 0 { - return rows - } - tx := db.DB("").Model(&model.UEEventAMF{}) - // 构建查询条件 - tx = tx.Where("id in ?", ids) - // 查询数据 - if err := tx.Find(&rows).Error; err != nil { - logger.Errorf("query find err => %v", err.Error()) - return rows - } - return rows -} - -// DeleteByIds 批量删除信息 -func (r UEEventAMF) DeleteByIds(ids []int64) int64 { - if len(ids) <= 0 { - return 0 - } - tx := db.DB("").Where("id in ?", ids) - if err := tx.Delete(&model.UEEventAMF{}).Error; err != nil { - logger.Errorf("delete err => %v", err.Error()) - return 0 - } - return tx.RowsAffected -} diff --git a/src/modules/network_data/repository/ue_event_mme.go b/src/modules/network_data/repository/ue_event_mme.go deleted file mode 100644 index ffcb6262..00000000 --- a/src/modules/network_data/repository/ue_event_mme.go +++ /dev/null @@ -1,98 +0,0 @@ -package repository - -import ( - "strings" - - "be.ems/src/framework/database/db" - "be.ems/src/framework/logger" - "be.ems/src/modules/network_data/model" -) - -// 实例化数据层 UEEventMME 结构体 -var NewUEEventMME = &UEEventMME{} - -// UEEventMME UE会话事件 数据层处理 -type UEEventMME struct{} - -// SelectByPage 分页查询集合 -func (r UEEventMME) SelectByPage(query model.UEEventMMEQuery) ([]model.UEEventMME, int64) { - tx := db.DB("").Model(&model.UEEventMME{}) - // 查询条件拼接 - if query.NeType != "" { - tx = tx.Where("ne_type = ?", query.NeType) - } - if query.RmUID != "" { - tx = tx.Where("rm_uid = ?", query.RmUID) - } - if query.BeginTime != 0 { - tx = tx.Where("timestamp >= ?", query.BeginTime) - } - if query.EndTime != 0 { - tx = tx.Where("timestamp <= ?", query.EndTime) - } - if query.EventType != "" { - eventTypes := strings.Split(query.EventType, ",") - tx = tx.Where("event_type in ?", eventTypes) - } - if query.IMSI != "" { - tx = tx.Where("JSON_EXTRACT(event_json, '$.imsi') = ?", query.IMSI) - } - - // 查询结果 - var total int64 = 0 - rows := []model.UEEventMME{} - - // 查询数量为0直接返回 - if err := tx.Count(&total).Error; err != nil || total <= 0 { - return rows, total - } - - // 排序 - if query.SortField != "" { - sortField := query.SortField - if query.SortOrder == "desc" { - sortField = sortField + " desc" - } - tx = tx.Order(sortField) - } - - // 查询数据分页 - pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize) - tx = tx.Limit(pageSize).Offset(pageSize * pageNum) - err := tx.Find(&rows).Error - if err != nil { - logger.Errorf("query find err => %v", err.Error()) - return rows, total - } - return rows, total -} - -// SelectByIds 通过ID查询 -func (r UEEventMME) SelectByIds(ids []int64) []model.UEEventMME { - rows := []model.UEEventMME{} - if len(ids) <= 0 { - return rows - } - tx := db.DB("").Model(&model.UEEventMME{}) - // 构建查询条件 - tx = tx.Where("id in ?", ids) - // 查询数据 - if err := tx.Find(&rows).Error; err != nil { - logger.Errorf("query find err => %v", err.Error()) - return rows - } - return rows -} - -// DeleteByIds 批量删除信息 -func (r UEEventMME) DeleteByIds(ids []int64) int64 { - if len(ids) <= 0 { - return 0 - } - tx := db.DB("").Where("id in ?", ids) - if err := tx.Delete(&model.UEEventMME{}).Error; err != nil { - logger.Errorf("delete err => %v", err.Error()) - return 0 - } - return tx.RowsAffected -} diff --git a/src/modules/network_data/service/ue_event.go b/src/modules/network_data/service/ue_event.go new file mode 100644 index 00000000..3f3d7a5f --- /dev/null +++ b/src/modules/network_data/service/ue_event.go @@ -0,0 +1,229 @@ +package service + +import ( + "encoding/json" + "fmt" + "strconv" + + "be.ems/src/framework/i18n" + "be.ems/src/framework/logger" + "be.ems/src/framework/utils/date" + "be.ems/src/framework/utils/file" + "be.ems/src/framework/utils/parse" + "be.ems/src/modules/network_data/model" + "be.ems/src/modules/network_data/repository" + sysService "be.ems/src/modules/system/service" + "github.com/tsmask/go-oam" +) + +// 实例化数据层 UEEvent 结构体 +var NewUEEvent = &UEEvent{ + ueEventRepository: repository.NewUEEvent, +} + +// UEEvent UE会话事件 服务层处理 +type UEEvent struct { + ueEventRepository *repository.UEEvent // UE会话事件数据信息 +} + +// FindByPage 根据条件分页查询 +func (r UEEvent) FindByPage(neType string, query map[string]string) ([]model.UEEvent, int64) { + return r.ueEventRepository.SelectByPage(neType, query) +} + +// DeleteByIds 批量删除信息 +func (r UEEvent) DeleteByIds(neType string, ids []int64) (int64, error) { + // 检查是否存在 + rows := r.ueEventRepository.SelectByIds(neType, ids) + if len(rows) <= 0 { + return 0, fmt.Errorf("no data") + } + + if len(rows) == len(ids) { + rows := r.ueEventRepository.DeleteByIds(neType, ids) + return rows, nil + } + // 删除信息失败! + return 0, fmt.Errorf("delete fail") +} + +// Insert 新增信息 +func (r UEEvent) Insert(param model.UEEvent) int64 { + return r.ueEventRepository.Insert(param) +} + +// ExportAMF 导出数据到 xlsx 文件 +func (r UEEvent) ExportAMF(rows []model.UEEvent, fileName, language string) (string, error) { + // 第一行表头标题 + headerCells := map[string]string{ + "A1": "ID", + "B1": "IMSI", + "C1": "Event Type", + "D1": "Result", + "E1": "Time", + } + // 读取字典数据 UE 事件类型 + dictUEEventType := sysService.NewSysDictData.FindByType("ue_event_type") + // 读取字典数据 UE 事件认证代码类型 + dictUEAauthCode := sysService.NewSysDictData.FindByType("ue_auth_code") + // 读取字典数据 UE 事件CM状态 + dictUEEventCmState := sysService.NewSysDictData.FindByType("ue_event_cm_state") + // 从第二行开始的数据 + dataCells := make([]map[string]any, 0) + for i, row := range rows { + idx := strconv.Itoa(i + 2) + // 解析 JSON 字符串为 map + var eventJSON map[string]interface{} + err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON) + if err != nil { + logger.Warnf("UEExport Error parsing JSON: %s", err.Error()) + continue + } + + // 取IMSI + imsi := "" + if v, ok := eventJSON["imsi"]; ok && v != nil { + imsi = v.(string) + } + // 取类型 + eventType := "" + for _, v := range dictUEEventType { + if row.EventType == v.DataValue { + eventType = i18n.TKey(language, v.DataLabel) + break + } + } + // 取结果 + eventResult := "" + // 取时间 + timeStr := "" + if row.EventType == oam.UENB_TYPE_AUTH { + if v, ok := eventJSON["authTime"]; ok && v != nil { + timeStr = v.(string) + } + if v, ok := eventJSON["authCode"]; ok && v != nil { + eventResult = v.(string) + for _, v := range dictUEAauthCode { + if eventResult == v.DataValue { + eventResult = i18n.TKey(language, v.DataLabel) + break + } + } + } + } + if row.EventType == oam.UENB_TYPE_DETACH { + if v, ok := eventJSON["detachTime"]; ok && v != nil { + timeStr = v.(string) + } + eventResult = "Success" + } + if row.EventType == oam.UENB_TYPE_CM { + if v, ok := eventJSON["changeTime"]; ok && v != nil { + timeStr = v.(string) + } + if v, ok := eventJSON["status"]; ok && v != nil { + eventResult = fmt.Sprint(v) + for _, v := range dictUEEventCmState { + if eventResult == v.DataValue { + eventResult = i18n.TKey(language, v.DataLabel) + break + } + } + } + } + + dataCells = append(dataCells, map[string]any{ + "A" + idx: row.ID, + "B" + idx: imsi, + "C" + idx: eventType, + "D" + idx: eventResult, + "E" + idx: timeStr, + }) + } + + // 导出数据表格 + return file.WriteSheet(headerCells, dataCells, fileName, "") +} + +// ExportMME 导出数据到 xlsx 文件 +func (r UEEvent) ExportMME(rows []model.UEEvent, fileName, language string) (string, error) { + // 第一行表头标题 + headerCells := map[string]string{ + "A1": "ID", + "B1": "IMSI", + "C1": "Event Type", + "D1": "Result", + "E1": "Time", + } + // 读取字典数据 UE 事件类型 + dictUEEventType := sysService.NewSysDictData.FindByType("ue_event_type") + // 读取字典数据 UE 事件认证代码类型 + dictUEAauthCode := sysService.NewSysDictData.FindByType("ue_auth_code") + // 读取字典数据 UE 事件CM状态 + dictUEEventCmState := sysService.NewSysDictData.FindByType("ue_event_cm_state") + // 从第二行开始的数据 + dataCells := make([]map[string]any, 0) + for i, row := range rows { + idx := strconv.Itoa(i + 2) + // 解析 JSON 字符串为 map + var eventJSON map[string]interface{} + err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON) + if err != nil { + logger.Warnf("UEExport Error parsing JSON: %s", err.Error()) + continue + } + + // 取IMSI + imsi := "" + if v, ok := eventJSON["imsi"]; ok && v != nil { + imsi = v.(string) + } + // 取类型 + eventType := row.EventType + for _, v := range dictUEEventType { + if row.EventType == v.DataValue { + eventType = i18n.TKey(language, v.DataLabel) + break + } + } + // 取结果 + eventResult := "" + if v, ok := eventJSON["result"]; ok && v != nil { + eventResult = v.(string) + if row.EventType == oam.UENB_TYPE_AUTH { + for _, v := range dictUEAauthCode { + if eventResult == v.DataValue { + eventResult = i18n.TKey(language, v.DataLabel) + break + } + } + } + if row.EventType == oam.UENB_TYPE_CM { + for _, v := range dictUEEventCmState { + if eventResult == v.DataValue { + eventResult = i18n.TKey(language, v.DataLabel) + break + } + } + } + } + // 取时间 + timeStr := "" + if v, ok := eventJSON["timestamp"]; ok && v != nil { + rowTime := parse.Number(v) + timeStr = date.ParseDateToStr(rowTime, date.YYYY_MM_DDTHH_MM_SSZ) + } + + dataCells = append(dataCells, map[string]any{ + "A" + idx: row.ID, + "B" + idx: imsi, + "C" + idx: eventType, + "D" + idx: eventResult, + "E" + idx: timeStr, + }) + } + + // 导出数据表格 + return file.WriteSheet(headerCells, dataCells, fileName, "") + +} diff --git a/src/modules/network_data/service/ue_event_amf.go b/src/modules/network_data/service/ue_event_amf.go deleted file mode 100644 index 4ff49c8a..00000000 --- a/src/modules/network_data/service/ue_event_amf.go +++ /dev/null @@ -1,138 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "strconv" - - "be.ems/src/framework/i18n" - "be.ems/src/framework/logger" - "be.ems/src/framework/utils/file" - "be.ems/src/modules/network_data/model" - "be.ems/src/modules/network_data/repository" - sysService "be.ems/src/modules/system/service" -) - -// 实例化数据层 UEEventAMF 结构体 -var NewUEEventAMF = &UEEventAMF{ - ueEventRepository: repository.NewUEEventAMF, -} - -// UEEventAMF UE会话事件AMF 服务层处理 -type UEEventAMF struct { - ueEventRepository *repository.UEEventAMF // UE会话事件数据信息 -} - -// FindByPage 根据条件分页查询 -func (r *UEEventAMF) FindByPage(querys model.UEEventAMFQuery) ([]model.UEEventAMF, int64) { - return r.ueEventRepository.SelectByPage(querys) -} - -// DeleteByIds 批量删除信息 -func (r *UEEventAMF) DeleteByIds(ids []int64) (int64, error) { - // 检查是否存在 - rows := r.ueEventRepository.SelectByIds(ids) - if len(rows) <= 0 { - return 0, fmt.Errorf("no data") - } - - if len(rows) == len(ids) { - rows := r.ueEventRepository.DeleteByIds(ids) - return rows, nil - } - // 删除信息失败! - return 0, fmt.Errorf("delete fail") -} - -// ExportXlsx 导出数据到 xlsx 文件 -func (r UEEventAMF) ExportXlsx(rows []model.UEEventAMF, fileName, language string) (string, error) { - // 第一行表头标题 - headerCells := map[string]string{ - "A1": "ID", - "B1": "IMSI", - "C1": "Event Type", - "D1": "Result", - "E1": "Time", - } - // 读取字典数据 UE 事件类型 - dictUEEventType := sysService.NewSysDictData.FindByType("ue_event_type") - // 读取字典数据 UE 事件认证代码类型 - dictUEAauthCode := sysService.NewSysDictData.FindByType("ue_auth_code") - // 读取字典数据 UE 事件CM状态 - dictUEEventCmState := sysService.NewSysDictData.FindByType("ue_event_cm_state") - // 从第二行开始的数据 - dataCells := make([]map[string]any, 0) - for i, row := range rows { - idx := strconv.Itoa(i + 2) - // 解析 JSON 字符串为 map - var eventJSON map[string]interface{} - err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON) - if err != nil { - logger.Warnf("UEExport Error parsing JSON: %s", err.Error()) - continue - } - - // 取IMSI - imsi := "" - if v, ok := eventJSON["imsi"]; ok && v != nil { - imsi = v.(string) - } - // 取类型 - eventType := "" - for _, v := range dictUEEventType { - if row.EventType == v.DataValue { - eventType = i18n.TKey(language, v.DataLabel) - break - } - } - // 取结果 - eventResult := "" - // 取时间 - timeStr := "" - if row.EventType == "auth-result" { - if v, ok := eventJSON["authTime"]; ok && v != nil { - timeStr = v.(string) - } - if v, ok := eventJSON["authCode"]; ok && v != nil { - eventResult = v.(string) - for _, v := range dictUEAauthCode { - if eventResult == v.DataValue { - eventResult = i18n.TKey(language, v.DataLabel) - break - } - } - } - } - if row.EventType == "detach" { - if v, ok := eventJSON["detachTime"]; ok && v != nil { - timeStr = v.(string) - } - eventResult = "Success" - } - if row.EventType == "cm-state" { - if v, ok := eventJSON["changeTime"]; ok && v != nil { - timeStr = v.(string) - } - if v, ok := eventJSON["status"]; ok && v != nil { - eventResult = fmt.Sprint(v) - for _, v := range dictUEEventCmState { - if eventResult == v.DataValue { - eventResult = i18n.TKey(language, v.DataLabel) - break - } - } - } - } - - dataCells = append(dataCells, map[string]any{ - "A" + idx: row.ID, - "B" + idx: imsi, - "C" + idx: eventType, - "D" + idx: eventResult, - "E" + idx: timeStr, - }) - } - - // 导出数据表格 - return file.WriteSheet(headerCells, dataCells, fileName, "") -} diff --git a/src/modules/network_data/service/ue_event_mme.go b/src/modules/network_data/service/ue_event_mme.go deleted file mode 100644 index 87cf9c25..00000000 --- a/src/modules/network_data/service/ue_event_mme.go +++ /dev/null @@ -1,130 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "strconv" - - "be.ems/src/framework/i18n" - "be.ems/src/framework/logger" - "be.ems/src/framework/utils/date" - "be.ems/src/framework/utils/file" - "be.ems/src/framework/utils/parse" - "be.ems/src/modules/network_data/model" - "be.ems/src/modules/network_data/repository" - sysService "be.ems/src/modules/system/service" -) - -// 实例化数据层 UEEventMME 结构体 -var NewUEEventMME = &UEEventMME{ - ueEventRepository: repository.NewUEEventMME, -} - -// UEEventMME UE会话事件MME 服务层处理 -type UEEventMME struct { - ueEventRepository *repository.UEEventMME // UE会话事件数据信息 -} - -// FindByPage 根据条件分页查询 -func (r *UEEventMME) FindByPage(querys model.UEEventMMEQuery) ([]model.UEEventMME, int64) { - return r.ueEventRepository.SelectByPage(querys) -} - -// DeleteByIds 批量删除信息 -func (r *UEEventMME) DeleteByIds(ids []int64) (int64, error) { - // 检查是否存在 - rows := r.ueEventRepository.SelectByIds(ids) - if len(rows) <= 0 { - return 0, fmt.Errorf("no data") - } - - if len(rows) == len(ids) { - rows := r.ueEventRepository.DeleteByIds(ids) - return rows, nil - } - // 删除信息失败! - return 0, fmt.Errorf("delete fail") -} - -// ExportXlsx 导出数据到 xlsx 文件 -func (r UEEventMME) ExportXlsx(rows []model.UEEventMME, fileName, language string) (string, error) { - // 第一行表头标题 - headerCells := map[string]string{ - "A1": "ID", - "B1": "IMSI", - "C1": "Event Type", - "D1": "Result", - "E1": "Time", - } - // 读取字典数据 UE 事件类型 - dictUEEventType := sysService.NewSysDictData.FindByType("ue_event_type") - // 读取字典数据 UE 事件认证代码类型 - dictUEAauthCode := sysService.NewSysDictData.FindByType("ue_auth_code") - // 读取字典数据 UE 事件CM状态 - dictUEEventCmState := sysService.NewSysDictData.FindByType("ue_event_cm_state") - // 从第二行开始的数据 - dataCells := make([]map[string]any, 0) - for i, row := range rows { - idx := strconv.Itoa(i + 2) - // 解析 JSON 字符串为 map - var eventJSON map[string]interface{} - err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON) - if err != nil { - logger.Warnf("UEExport Error parsing JSON: %s", err.Error()) - continue - } - - // 取IMSI - imsi := "" - if v, ok := eventJSON["imsi"]; ok && v != nil { - imsi = v.(string) - } - // 取类型 - eventType := row.EventType - for _, v := range dictUEEventType { - if row.EventType == v.DataValue { - eventType = i18n.TKey(language, v.DataLabel) - break - } - } - // 取结果 - eventResult := "" - if v, ok := eventJSON["result"]; ok && v != nil { - eventResult = v.(string) - if row.EventType == "auth-result" { - for _, v := range dictUEAauthCode { - if eventResult == v.DataValue { - eventResult = i18n.TKey(language, v.DataLabel) - break - } - } - } - if row.EventType == "cm-state" { - for _, v := range dictUEEventCmState { - if eventResult == v.DataValue { - eventResult = i18n.TKey(language, v.DataLabel) - break - } - } - } - } - // 取时间 - timeStr := "" - if v, ok := eventJSON["timestamp"]; ok && v != nil { - rowTime := parse.Number(v) - timeStr = date.ParseDateToStr(rowTime, date.YYYY_MM_DDTHH_MM_SSZ) - } - - dataCells = append(dataCells, map[string]any{ - "A" + idx: row.ID, - "B" + idx: imsi, - "C" + idx: eventType, - "D" + idx: eventResult, - "E" + idx: timeStr, - }) - } - - // 导出数据表格 - return file.WriteSheet(headerCells, dataCells, fileName, "") - -} diff --git a/src/modules/oam/service/ue_nb.go b/src/modules/oam/service/ue_nb.go new file mode 100644 index 00000000..5a419049 --- /dev/null +++ b/src/modules/oam/service/ue_nb.go @@ -0,0 +1,64 @@ +package service + +import ( + "encoding/json" + "fmt" + + "be.ems/src/framework/logger" + "github.com/tsmask/go-oam" + + neDataModel "be.ems/src/modules/network_data/model" + neDataService "be.ems/src/modules/network_data/service" + neService "be.ems/src/modules/network_element/service" + wsService "be.ems/src/modules/ws/service" +) + +// 实例化服务层 UENB 结构体 +var NewUENB = &UENB{ + neInfoService: neService.NewNeInfo, + wsService: wsService.NewWSSend, + ueEventService: neDataService.NewUEEvent, +} + +// UENB 消息处理 +type UENB struct { + neInfoService *neService.NeInfo + wsService *wsService.WSSend + ueEventService *neDataService.UEEvent // UE会话事件服务 +} + +// Resolve 接收处理 +func (s *UENB) Resolve(u oam.UENB) error { + // 是否存在网元 + neInfo := s.neInfoService.FindByRmuid(u.NeUid) + if neInfo.NeType == "" || neInfo.RmUID != u.NeUid { + logger.Warnf("resolve ue_nb network element does not exist %s", u.NeUid) + return fmt.Errorf("resolve ue_nb network element does not exist %s", u.NeUid) + } + + uenbByte, _ := json.Marshal(u) + uenbEvent := neDataModel.UEEvent{ + NeType: neInfo.NeType, + NeName: neInfo.NeName, + RmUID: neInfo.RmUID, + Timestamp: u.RecordTime, + EventType: u.Type, + EventJSONStr: string(uenbByte), + } + insertId := s.ueEventService.Insert(uenbEvent) + if insertId <= 0 { + return fmt.Errorf("add ue_nb data fail") + } + uenbEvent.ID = insertId + + // 推送到ws订阅组 + switch neInfo.NeType { + case "AMF": + s.wsService.ByGroupID(wsService.GROUP_AMF_UE, uenbEvent) + s.wsService.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_AMF_UE, neInfo.NeId), uenbEvent) + case "MME": + s.wsService.ByGroupID(wsService.GROUP_MME_UE, uenbEvent) + s.wsService.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_MME_UE, neInfo.NeId), uenbEvent) + } + return nil +} diff --git a/src/modules/ws/processor/ue_connect.go b/src/modules/ws/processor/ue_connect.go index 79d99952..20ebf461 100644 --- a/src/modules/ws/processor/ue_connect.go +++ b/src/modules/ws/processor/ue_connect.go @@ -6,54 +6,29 @@ import ( "be.ems/src/framework/logger" "be.ems/src/framework/resp" - neDataModel "be.ems/src/modules/network_data/model" neDataService "be.ems/src/modules/network_data/service" neService "be.ems/src/modules/network_element/service" ) -// GetUEConnectByAMF 获取UE会话事件-AMF -func GetUEConnectByAMF(requestID string, data any) ([]byte, error) { - msgByte, _ := json.Marshal(data) - var query neDataModel.UEEventAMFQuery - err := json.Unmarshal(msgByte, &query) - if err != nil { - logger.Warnf("ws processor GetUEConnectByAMF err: %s", err.Error()) - return nil, fmt.Errorf("query data structure error") +// GetUEConnect 获取UE会话事件 +func GetUEConnect(requestID string, data any) ([]byte, error) { + if data == nil { + logger.Errorf("ws processor GetUEConnect data is nil") + return nil, fmt.Errorf("query data error") + } + dataMap := data.(map[string]any) + query := make(map[string]string, 0) + for k, v := range dataMap { + query[k] = fmt.Sprintf("%v", v) } - // 查询网元获取IP - neInfo := neService.NewNeInfo.FindByNeTypeAndNeID("AMF", query.NeID) - if neInfo.NeId != query.NeID || neInfo.IP == "" { - return nil, fmt.Errorf("not fount neId info") + // 查询网元信息 rmUID + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(query["neType"], query["neId"]) + if neInfo.NeType == "" { + return nil, fmt.Errorf("query neinfo not found") } - query.RmUID = neInfo.RmUID - - rows, total := neDataService.NewUEEventAMF.FindByPage(query) - resultByte, err := json.Marshal(resp.Ok(map[string]any{ - "requestId": requestID, - "data": map[string]any{"rows": rows, "total": total}, - })) - return resultByte, err -} - -// GetUEConnectByMME 获取UE会话事件-MME -func GetUEConnectByMME(requestID string, data any) ([]byte, error) { - msgByte, _ := json.Marshal(data) - var query neDataModel.UEEventMMEQuery - err := json.Unmarshal(msgByte, &query) - if err != nil { - logger.Warnf("ws processor GetUEConnectByMME err: %s", err.Error()) - return nil, fmt.Errorf("query data structure error") - } - - // 查询网元获取IP - neInfo := neService.NewNeInfo.FindByNeTypeAndNeID("MME", query.NeID) - if neInfo.NeId != query.NeID || neInfo.IP == "" { - return nil, fmt.Errorf("not fount neId info") - } - query.RmUID = neInfo.RmUID - - rows, total := neDataService.NewUEEventMME.FindByPage(query) + query["rmUID"] = neInfo.RmUID + rows, total := neDataService.NewUEEvent.FindByPage(neInfo.NeType, query) resultByte, err := json.Marshal(resp.Ok(map[string]any{ "requestId": requestID, "data": map[string]any{"rows": rows, "total": total},