diff --git a/src/modules/network_data/controller/alarm.go b/src/modules/network_data/controller/alarm.go new file mode 100644 index 0000000..866db69 --- /dev/null +++ b/src/modules/network_data/controller/alarm.go @@ -0,0 +1,81 @@ +package controller + +import ( + "strings" + + "nms_nbi/src/framework/i18n" + "nms_nbi/src/framework/utils/ctx" + "nms_nbi/src/framework/utils/parse" + "nms_nbi/src/framework/vo/result" + "nms_nbi/src/modules/network_data/model" + neDataService "nms_nbi/src/modules/network_data/service" + neService "nms_nbi/src/modules/network_element/service" + + "github.com/gin-gonic/gin" +) + +// 实例化控制层 AlarmController 结构体 +var NewAlarmController = &AlarmController{ + neInfoService: neService.NewNeInfoImpl, + alarmService: neDataService.NewAlarmImpl, +} + +// 告警数据 +// +// PATH /alarm +type AlarmController struct { + // 网元信息服务 + neInfoService neService.INeInfo + // 告警信息服务 + alarmService neDataService.IAlarm +} + +// 告警列表 +// +// GET /list +func (s *AlarmController) List(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var querys model.AlarmQuery + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 查询网元获取IP + neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) + if neInfo.NeId != querys.NeID || neInfo.IP == "" { + c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + return + } + querys.RmUID = neInfo.RmUID + + // 查询数据 + data := s.alarmService.SelectPage(querys) + c.JSON(200, result.Ok(data)) +} + +// 告警删除 +// +// DELETE /:alarmIds +func (s *AlarmController) Remove(c *gin.Context) { + language := ctx.AcceptLanguage(c) + alarmIds := c.Param("alarmIds") + if alarmIds == "" { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + // 处理字符转id数组后去重 + ids := strings.Split(alarmIds, ",") + uniqueIDs := parse.RemoveDuplicates(ids) + if len(uniqueIDs) <= 0 { + c.JSON(200, result.Err(nil)) + return + } + rows, err := s.alarmService.DeleteByIds(uniqueIDs) + if err != nil { + c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + return + } + msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) + c.JSON(200, result.OkMsg(msg)) +} diff --git a/src/modules/network_data/model/alarm.go b/src/modules/network_data/model/alarm.go new file mode 100644 index 0000000..4e4bc9a --- /dev/null +++ b/src/modules/network_data/model/alarm.go @@ -0,0 +1,57 @@ +package model + +import "time" + +// Alarm 告警数据对象 alarm +type Alarm struct { + ID string `json:"id" gorm:"id"` + AlarmSeq string `json:"alarmSeq" gorm:"alarm_seq"` + AlarmId string `json:"alarmId" gorm:"alarm_id"` + AlarmTitle string `json:"alarmTitle" gorm:"alarm_title"` + NeType string `json:"neType" gorm:"ne_type"` + NeId string `json:"neId" gorm:"ne_id"` + AlarmCode string `json:"alarmCode" gorm:"alarm_code"` + EventTime time.Time `json:"eventTime" gorm:"event_time"` + AlarmType string `json:"alarmType" gorm:"alarm_type"` + OrigSeverity string `json:"origSeverity" gorm:"orig_severity"` // 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) + PerceivedSeverity string `json:"perceivedSeverity" gorm:"perceived_severity"` // 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) + PvFlag string `json:"pvFlag" gorm:"pv_flag"` + NeName string `json:"neName" gorm:"ne_name"` + ObjectUid string `json:"objectUid" gorm:"object_uid"` + ObjectName string `json:"objectName" gorm:"object_name"` + ObjectType string `json:"objectType" gorm:"object_type"` + LocationInfo string `json:"locationInfo" gorm:"location_info"` + Province string `json:"province" gorm:"province"` + AlarmStatus string `json:"alarmStatus" gorm:"alarm_status"` // 0:clear, 1:active + SpecificProblem string `json:"specificProblem" gorm:"specific_problem"` + SpecificProblemId string `json:"specificProblemId" gorm:"specific_problem_id"` + AddInfo string `json:"addInfo" gorm:"add_info"` + Counter string `json:"counter" gorm:"counter"` + LatestEventTime time.Time `json:"latestEventTime" gorm:"latest_event_time"` + AckState string `json:"ackState" gorm:"ack_state"` // 0: Unacked, 1: Acked + AckTime time.Time `json:"ackTime" gorm:"ack_time"` + AckUser string `json:"ackUser" gorm:"ack_user"` + ClearType string `json:"clearType" gorm:"clear_type"` // 0: Unclear, 1: AutoClear, 2: ManualClear + ClearTime time.Time `json:"clearTime" gorm:"clear_time"` + ClearUser string `json:"clearUser" gorm:"clear_user"` + Timestamp time.Time `json:"timestamp" gorm:"timestamp"` +} + +// TableName 表名称 +func (*Alarm) TableName() string { + return "alarm" +} + +// AlarmQuery 告警数据查询参数结构体 +type AlarmQuery struct { + NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型 + NeID string `json:"neId" form:"neId" binding:"required"` + RmUID string `json:"rmUID" form:"rmUID"` + OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF) + StartTime string `json:"startTime" form:"startTime"` + EndTime string `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/network_data.go b/src/modules/network_data/network_data.go index 10e8df7..2391200 100644 --- a/src/modules/network_data/network_data.go +++ b/src/modules/network_data/network_data.go @@ -28,6 +28,19 @@ func Setup(router *gin.Engine) { ) } + // 告警数据信息 + alarmGroup := neDataGroup.Group("/alarm") + { + alarmGroup.GET("/list", + middleware.PreAuthorize(nil), + controller.NewAlarmController.List, + ) + alarmGroup.DELETE("/:alarmIds", + middleware.PreAuthorize(nil), + controller.NewAlarmController.Remove, + ) + } + // 网元IMS imsGroup := neDataGroup.Group("/ims") { diff --git a/src/modules/network_data/repository/alarm.go b/src/modules/network_data/repository/alarm.go new file mode 100644 index 0000000..da97f5d --- /dev/null +++ b/src/modules/network_data/repository/alarm.go @@ -0,0 +1,15 @@ +package repository + +import "nms_nbi/src/modules/network_data/model" + +// 告警 数据层接口 +type IAlarm interface { + // SelectPage 根据条件分页查询 + SelectPage(querys model.AlarmQuery) map[string]any + + // SelectByIds 通过ID查询 + SelectByIds(ids []string) []model.Alarm + + // DeleteByIds 批量删除信息 + DeleteByIds(ids []string) int64 +} diff --git a/src/modules/network_data/repository/alarm.impl.go b/src/modules/network_data/repository/alarm.impl.go new file mode 100644 index 0000000..69e12cb --- /dev/null +++ b/src/modules/network_data/repository/alarm.impl.go @@ -0,0 +1,194 @@ +package repository + +import ( + "fmt" + "strings" + + "nms_nbi/src/framework/datasource" + "nms_nbi/src/framework/logger" + "nms_nbi/src/framework/utils/parse" + "nms_nbi/src/framework/utils/repo" + "nms_nbi/src/modules/network_data/model" +) + +// 实例化数据层 AlarmImpl 结构体 +var NewAlarmImpl = &AlarmImpl{ + selectSql: `select + id, alarm_seq, alarm_id, alarm_title, ne_type, ne_id, alarm_code, event_time, + alarm_type, orig_severity, perceived_severity, pv_flag, ne_name, object_uid, object_name, + object_type, location_info, province, alarm_status, specific_problem, specific_problem_id, + add_info, counter, latest_event_time, ack_state, ack_time, ack_user, clear_type, + clear_time, clear_user, timestamp + from alarm`, + + resultMap: map[string]string{ + "id": "ID", + "alarm_seq": "AlarmSeq", + "alarm_id": "AlarmId", + "alarm_title": "AlarmTitle", + "ne_type": "NeType", + "ne_id": "NeId", + "alarm_code": "AlarmCode", + "event_time": "EventTime", + "alarm_type": "AlarmType", + "orig_severity": "OrigSeverity", + "perceived_severity": "PerceivedSeverity", + "pv_flag": "PvFlag", + "ne_name": "NeName", + "object_uid": "ObjectUid", + "object_name": "ObjectName", + "object_type": "ObjectType", + "location_info": "LocationInfo", + "province": "Province", + "alarm_status": "AlarmStatus", + "specific_problem": "SpecificProblem", + "specific_problem_id": "SpecificProblemId", + "add_info": "AddInfo", + "counter": "Counter", + "latest_event_time": "LatestEventTime", + "ack_state": "AckState", + "ack_time": "AckTime", + "ack_user": "AckUser", + "clear_type": "ClearType", + "clear_time": "ClearTime", + "clear_user": "ClearUser", + "timestamp": "Timestamp", + }, +} + +// AlarmImpl 告警 数据层处理 +type AlarmImpl struct { + // 查询视图对象SQL + selectSql string + // 结果字段与实体映射 + resultMap map[string]string +} + +// convertResultRows 将结果记录转实体结果组 +func (r *AlarmImpl) convertResultRows(rows []map[string]any) []model.Alarm { + arr := make([]model.Alarm, 0) + for _, row := range rows { + item := model.Alarm{} + for key, value := range row { + if keyMapper, ok := r.resultMap[key]; ok { + repo.SetFieldValue(&item, keyMapper, value) + } + } + arr = append(arr, item) + } + return arr +} + +// SelectPage 根据条件分页查询 +func (r *AlarmImpl) SelectPage(querys model.AlarmQuery) map[string]any { + // 查询条件拼接 + var conditions []string + var params []any + if querys.NeType != "" { + conditions = append(conditions, "ne_type = ?") + params = append(params, querys.NeType) + } + if querys.RmUID != "" { + conditions = append(conditions, "object_uid = ?") + params = append(params, querys.RmUID) + } + if querys.StartTime != "" { + conditions = append(conditions, "timestamp >= ?") + params = append(params, querys.StartTime) + } + if querys.EndTime != "" { + conditions = append(conditions, "timestamp <= ?") + params = append(params, querys.EndTime) + } + if querys.OrigSeverity != "" { + eventTypes := strings.Split(querys.OrigSeverity, ",") + placeholder := repo.KeyPlaceholderByQuery(len(eventTypes)) + conditions = append(conditions, fmt.Sprintf("orig_severity in (%s)", placeholder)) + for _, eventType := range eventTypes { + params = append(params, eventType) + } + } + + // 构建查询条件语句 + whereSql := "" + if len(conditions) > 0 { + whereSql += " where " + strings.Join(conditions, " and ") + } + + result := map[string]any{ + "total": 0, + "rows": []model.Alarm{}, + } + + // 查询数量 长度为0直接返回 + totalSql := "select count(1) as 'total' from alarm" + totalRows, err := datasource.RawDB("", totalSql+whereSql, params) + if err != nil { + logger.Errorf("total err => %v", err) + return result + } + total := parse.Number(totalRows[0]["total"]) + if total == 0 { + return result + } else { + result["total"] = total + } + + // 分页 + pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize) + pageSql := " limit ?,? " + params = append(params, pageNum*pageSize) + params = append(params, pageSize) + + // 排序 + orderSql := "" + if querys.SortField != "" { + sortSql := querys.SortField + if querys.SortOrder != "" { + if querys.SortOrder == "desc" { + sortSql += " desc " + } else { + sortSql += " asc " + } + } + orderSql = fmt.Sprintf(" order by %s ", sortSql) + } + + // 查询数据 + querySql := r.selectSql + whereSql + orderSql + pageSql + results, err := datasource.RawDB("", querySql, params) + if err != nil { + logger.Errorf("query err => %v", err) + } + + // 转换实体 + result["rows"] = r.convertResultRows(results) + return result +} + +// SelectByIds 通过ID查询 +func (r *AlarmImpl) SelectByIds(ids []string) []model.Alarm { + placeholder := repo.KeyPlaceholderByQuery(len(ids)) + querySql := r.selectSql + " where id in (" + placeholder + ")" + parameters := repo.ConvertIdsSlice(ids) + results, err := datasource.RawDB("", querySql, parameters) + if err != nil { + logger.Errorf("query err => %v", err) + return []model.Alarm{} + } + // 转换实体 + return r.convertResultRows(results) +} + +// DeleteByIds 批量删除信息 +func (r *AlarmImpl) DeleteByIds(ids []string) int64 { + placeholder := repo.KeyPlaceholderByQuery(len(ids)) + sql := "delete from alarm where id in (" + placeholder + ")" + parameters := repo.ConvertIdsSlice(ids) + results, err := datasource.ExecDB("", sql, parameters) + if err != nil { + logger.Errorf("delete err => %v", err) + return 0 + } + return results +} diff --git a/src/modules/network_data/service/alarm.go b/src/modules/network_data/service/alarm.go new file mode 100644 index 0000000..d9a1af4 --- /dev/null +++ b/src/modules/network_data/service/alarm.go @@ -0,0 +1,12 @@ +package service + +import "nms_nbi/src/modules/network_data/model" + +// 告警 服务层接口 +type IAlarm interface { + // SelectPage 根据条件分页查询 + SelectPage(querys model.AlarmQuery) map[string]any + + // DeleteByIds 批量删除信息 + DeleteByIds(ids []string) (int64, error) +} diff --git a/src/modules/network_data/service/alarm.impl.go b/src/modules/network_data/service/alarm.impl.go new file mode 100644 index 0000000..a6d3946 --- /dev/null +++ b/src/modules/network_data/service/alarm.impl.go @@ -0,0 +1,40 @@ +package service + +import ( + "fmt" + + "nms_nbi/src/modules/network_data/model" + "nms_nbi/src/modules/network_data/repository" +) + +// 实例化数据层 AlarmImpl 结构体 +var NewAlarmImpl = &AlarmImpl{ + alarmRepository: repository.NewAlarmImpl, +} + +// AlarmImpl 告警 服务层处理 +type AlarmImpl struct { + // 告警数据信息 + alarmRepository repository.IAlarm +} + +// SelectPage 根据条件分页查询 +func (r *AlarmImpl) SelectPage(querys model.AlarmQuery) map[string]any { + return r.alarmRepository.SelectPage(querys) +} + +// DeleteByIds 批量删除信息 +func (r *AlarmImpl) DeleteByIds(ids []string) (int64, error) { + // 检查是否存在 + data := r.alarmRepository.SelectByIds(ids) + if len(data) <= 0 { + return 0, fmt.Errorf("no data") + } + + if len(data) == len(ids) { + rows := r.alarmRepository.DeleteByIds(ids) + return rows, nil + } + // 删除信息失败! + return 0, fmt.Errorf("delete fail") +}