ref: v3变更,,完成整合,同步v2.2508.4 -250902

This commit is contained in:
TsMask
2025-09-06 11:17:18 +08:00
parent 382bc311e6
commit 10cf6bbd2a
36 changed files with 527 additions and 478 deletions

View File

@@ -210,7 +210,7 @@ func (s *AMFController) NbInfoList(c *gin.Context) {
// 接入基站状态信息列表
//
// GET /nb/list-cfg
// GET /nb/addrs
//
// @Tags ne_data/amf
// @Accept json
@@ -220,7 +220,7 @@ func (s *AMFController) NbInfoList(c *gin.Context) {
// @Security TokenAuth
// @Summary Access to the base station status information list
// @Description Access to the base station status information list
// @Router /neData/amf/nb/list-cfg [get]
// @Router /neData/amf/nb/addrs [get]
func (s *AMFController) NbStateList(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {

View File

@@ -17,16 +17,18 @@ import (
// 实例化控制层 IMSController 结构体
var NewIMS = &IMSController{
neInfoService: neService.NewNeInfo,
cdrEventService: neDataService.NewCDREvent,
neInfoService: neService.NewNeInfo,
cdrEventService: neDataService.NewCDREvent,
kpiReportService: neDataService.NewKpiReport,
}
// 网元IMS
//
// PATH /ims
type IMSController struct {
neInfoService *neService.NeInfo // 网元信息服务
cdrEventService *neDataService.CDREvent // CDR会话事件服务
neInfoService *neService.NeInfo // 网元信息服务
cdrEventService *neDataService.CDREvent // CDR会话事件服务
kpiReportService *neDataService.KpiReport // 统计信息服务
}
// CDR会话列表
@@ -253,3 +255,45 @@ func (s *IMSController) UeSessionList(c *gin.Context) {
c.JSON(200, resp.OkData(data))
}
// KPI 忙时统计
//
// GET /kpi/busy-hour
//
// @Tags network_data/ims
// @Accept json
// @Produce json
// @Param neId query string true "NE ID" default(001)
// @Param timestamp query int64 false "timestamp"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Busy hour statistics
// @Description Busy hour statistics
// @Router /neData/ims/kpi/busy-hour [get]
func (s IMSController) KPIBusyHour(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
CoreUID string `form:"coreUid" binding:"required"` // 核心网唯一标识
NeUID string `form:"neUid" binding:"required"` // 网元唯一标识
Timestamp int64 `form:"timestamp" binding:"required"` // 时间戳毫秒 年月日返回每小时的总和 年月日时返回该小时的总和
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if query.Timestamp < 1e12 || query.Timestamp > 1e13 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "timestamp format is ms"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByCoreUidAndNeUid(query.CoreUID, query.NeUID)
if neInfo.CoreUID != query.CoreUID || neInfo.NeUID != query.NeUID {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
data := s.kpiReportService.IMSBusyHour(neInfo.CoreUID, neInfo.NeUID, query.Timestamp)
c.JSON(200, resp.OkData(data))
}

View File

@@ -210,7 +210,7 @@ func (s *MMEController) NbInfoList(c *gin.Context) {
// 接入基站状态信息列表
//
// GET /nb/list-cfg
// GET /nb/addrs
//
// @Tags ne_data/mme
// @Accept json
@@ -220,7 +220,7 @@ func (s *MMEController) NbInfoList(c *gin.Context) {
// @Security TokenAuth
// @Summary Access to the base station status information list
// @Description Access to the base station status information list
// @Router /neData/mme/nb/list-cfg [get]
// @Router /neData/mme/nb/addrs [get]
func (s *MMEController) NbStateList(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {

View File

@@ -81,8 +81,8 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
// @Router /ne/link/udm/auth/list [get]
func (s *UDMAuthController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmAuthService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
rows, total := s.udmAuthService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// UDM鉴权用户信息
@@ -251,8 +251,8 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.IMSI == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: imsi is empty"))
if len(body.IMSI) != 15 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: IMSI length is not 15 bits"))
return
}
@@ -306,7 +306,7 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
CoreUID string `form:"coreUid" binding:"required"` // 核心网唯一标识
NeUID string `form:"neUid" binding:"required"` // 网元唯一标识
IMSI string `form:"imsi" binding:"required"` // IMSi
Num int64 `form:"num"` // 批量数量
Num int64 `form:"num"` // 数量 0可拼接imsi多删除 大于1为批
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
@@ -397,7 +397,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
}
fileType := c.Query("type")
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "file type error, only support csv,txt"))
return
}

View File

@@ -81,8 +81,8 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
// @Router /ne/link/udm/sub/list [get]
func (s *UDMSubController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmSubService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
rows, total := s.udmSubService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// UDM签约用户信息
@@ -247,12 +247,6 @@ func (s *UDMSubController) Add(c *gin.Context) {
// @Router /ne/link/udm/sub [put]
func (s *UDMSubController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
if neId == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: neId is empty"))
return
}
var body model.UDMSubUser
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
@@ -350,6 +344,7 @@ func (s *UDMSubController) Remove(c *gin.Context) {
s.udmSubService.LoadData(neInfo.CoreUID, neInfo.NeUID, query.IMSI, query.Num, "-(Deleted)-")
}
c.JSON(200, resp.OkData(data))
return
}
// 处理字符转id数组后去重
@@ -405,7 +400,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
}
fileType := c.Query("type")
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "file type error, only support csv,txt"))
return
}

View File

@@ -82,8 +82,8 @@ func (s *UDMVOIPController) ResetData(c *gin.Context) {
// @Router /ne/link/udm/voip/list [get]
func (s *UDMVOIPController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmVOIPService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
rows, total := s.udmVOIPService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// UDMVOIP用户信息
@@ -336,14 +336,14 @@ func (s *UDMVOIPController) Remove(c *gin.Context) {
func (s *UDMVOIPController) Export(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
neId := c.Query("neId")
fileType := c.Query("type")
if neId == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: neId is empty"))
neUid := c.Query("neUid")
if c.Query("coreUid") == "" || neUid == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: coreUid or neUid is empty"))
return
}
fileType := c.Query("type")
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg("file type error, only support csv,txt"))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "file type error, only support csv,txt"))
return
}
@@ -363,7 +363,7 @@ func (s *UDMVOIPController) Export(c *gin.Context) {
}
// 文件名
fileName := fmt.Sprintf("udm_voip_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
fileName := fmt.Sprintf("udm_voip_user_export_%s_%d.%s", neUid, time.Now().UnixMilli(), fileType)
filePath := filepath.Join(file.ParseUploadFileDir(constants.UPLOAD_EXPORT), fileName)
if fileType == "csv" {

View File

@@ -81,8 +81,8 @@ func (s *UDMVolteIMSController) ResetData(c *gin.Context) {
// @Router /ne/link/udm/volte-ims/list [get]
func (s *UDMVolteIMSController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmVolteIMSService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
rows, total := s.udmVolteIMSService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// UDMVolteIMS用户信息
@@ -260,12 +260,12 @@ func (s *UDMVolteIMSController) Add(c *gin.Context) {
func (s *UDMVolteIMSController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
CoreUID string `form:"coreUid" binding:"required"` // 核心网唯一标识
NeUID string `form:"neUid" binding:"required"` // 网元唯一标识
IMSI string `form:"imsi" binding:"required"` // IMSi, 带数量时为批量
MSISDN string `form:"msisdn" binding:"required"` // MSISDN, 带数量时为批量
Volte string `form:"volte" binding:"required,oneof=0 1"` // volte
Num int64 `form:"num"` // 批量数量
CoreUID string `form:"coreUid" binding:"required"` // 核心网唯一标识
NeUID string `form:"neUid" binding:"required"` // 网元唯一标识
IMSI string `form:"imsi" binding:"required"` // IMSi, 带数量时为批量
MSISDN string `form:"msisdn" binding:"required"` // MSISDN, 带数量时为批量
Tag string `form:"tag" binding:"required,oneof=0 1"` // tag
Num int64 `form:"num"` // 批量数量
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
@@ -291,10 +291,10 @@ func (s *UDMVolteIMSController) Remove(c *gin.Context) {
if query.Num > 1 {
// 发送MML
cmd := ""
if query.Volte == "0" {
if query.Tag == "0" {
cmd = fmt.Sprintf("bde imsuser:start_msisdn=%s,sub_num=%d,volte=0", query.MSISDN, query.Num)
}
if query.Volte == "1" {
if query.Tag == "1" {
cmd = fmt.Sprintf("bde imsuser:start_imsi=%s,start_msisdn=%s,sub_num=%d,volte=1", query.IMSI, query.MSISDN, query.Num)
}
data, err := telnet.ConvertToStr(telnetClient, cmd)
@@ -312,7 +312,7 @@ func (s *UDMVolteIMSController) Remove(c *gin.Context) {
}
// 发送MML
cmd := fmt.Sprintf("del imsuser:imsi=%s,msisdn=%s,volte=%s", query.IMSI, query.MSISDN, query.Volte)
cmd := fmt.Sprintf("del imsuser:imsi=%s,msisdn=%s,volte=%s", query.IMSI, query.MSISDN, query.Tag)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
@@ -352,7 +352,7 @@ func (s *UDMVolteIMSController) Export(c *gin.Context) {
}
fileType := c.Query("type")
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "file type error, only support csv,txt"))
return
}

View File

@@ -27,9 +27,9 @@ type UPFController struct {
}
// 总流量数 N3上行 N6下行
// 单位 比特(bit)
// 单位 字节(Byte)
//
// GET /flow-total
// GET /kpi/flow-total
//
// @Tags network_data/upf
// @Accept json
@@ -40,8 +40,8 @@ type UPFController struct {
// @Security TokenAuth
// @Summary Total number of flows N3 upstream N6 downstream
// @Description Total number of flows N3 upstream N6 downstream
// @Router /ne/link/upf/flow-total [get]
func (s UPFController) FlowTotal(c *gin.Context) {
// @Router /ne/link/upf/kpi/flow-total [get]
func (s UPFController) KPIFlowTotal(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
CoreUID string `form:"coreUid" binding:"required"` // 核心网唯一标识

View File

@@ -2,15 +2,16 @@ package model
// UDMAuthUser UDM鉴权用户 udm_auth
type UDMAuthUser struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
Amf string `json:"amf" gorm:"column:amf"` // AMF
Ki string `json:"ki" gorm:"column:ki"` // ki
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // algoIndex
Opc string `json:"opc" gorm:"column:opc"` // OPC
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid" binding:"required"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid" binding:"required"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type" binding:"required,oneof=UDM"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
Amf string `json:"amf" gorm:"column:amf"` // AMF
Ki string `json:"ki" gorm:"column:ki"` // ki
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // algoIndex
Opc string `json:"opc" gorm:"column:opc"` // OPC
CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间
}
// TableName 表名称

View File

@@ -2,12 +2,12 @@ package model
// UDMSubUser UDM签约用户 udm_sub
type UDMSubUser struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid" binding:"required"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid" binding:"required"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type" binding:"required,oneof=UDM"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
AmDat string `json:"amDat" gorm:"column:am_dat"` // AmData
UeAmbrTpl string `json:"ambr" gorm:"column:ambr"` // AmData SubUeAMBRTemp

View File

@@ -2,10 +2,10 @@ package model
// UDMVOIPUser UDMVOIP用户 udm_voip
type UDMVOIPUser struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid" binding:"required"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid" binding:"required"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type" binding:"required,oneof=UDM"` // 网元类型
UserName string `json:"username" gorm:"column:username"` // 用户名
Password string `json:"password" gorm:"column:password"` // 密码

View File

@@ -2,12 +2,12 @@ package model
// UDMVolteIMSUser UDMVolteIMS用户 udm_volte_ims
type UDMVolteIMSUser struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
CoreUID string `json:"coreUid" gorm:"column:core_uid" binding:"required"` // 核心网唯一标识
NeUID string `json:"neUid" gorm:"column:ne_uid" binding:"required"` // 网元唯一标识
NeType string `json:"neType" gorm:"column:ne_type" binding:"required,oneof=UDM"` // 网元类型
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
Tag string `json:"tag" gorm:"column:tag"` // 0=VoIP, 1=VoLTE
VNI string `json:"vni" gorm:"column:vni"` // VNI

View File

@@ -203,6 +203,10 @@ func Setup(router *gin.Engine) {
middleware.AuthorizeUser(nil),
controller.NewIMS.UeSessionList,
)
imsGroup.GET("/kpi/busy-hour",
middleware.AuthorizeUser(nil),
controller.NewIMS.KPIBusyHour,
)
}
// 网元SMSC
@@ -281,9 +285,9 @@ func Setup(router *gin.Engine) {
// 网元UPF
upfGroup := neDataGroup.Group("/upf")
{
upfGroup.GET("/flow-total",
upfGroup.GET("/kpi/flow-total",
middleware.AuthorizeUser(nil),
controller.NewUPF.FlowTotal,
controller.NewUPF.KPIFlowTotal,
)
}

View File

@@ -118,7 +118,24 @@ func (r KpiReport) SelectUPF(coreUid, neUid string, beginTime, endTime int64) []
tx = tx.Where("created_at <= ?", endTime)
// 查询数据
rows := []model.KpiReport{}
if err := tx.Select("kpi_values").Find(&rows).Error; err != nil {
if err := tx.Select("kpi_values", "created_at").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectIMS 查询IMS数据
func (r KpiReport) SelectIMS(coreUid, neUid string, beginTime, endTime int64) []model.KpiReport {
tx := db.DB("").Model(&model.KpiReport{})
// 表名
tx = tx.Table("kpi_report_ims")
tx = tx.Where("core_uid = ? and ne_uid = ?", coreUid, neUid)
tx = tx.Where("created_at >= ?", beginTime)
tx = tx.Where("created_at <= ?", endTime)
// 查询数据
rows := []model.KpiReport{}
if err := tx.Select("kpi_values", "created_at").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}

View File

@@ -173,7 +173,7 @@ func (r KpiReport) TitleInsert(param model.KpiTitle) int64 {
// UPFTodayFlowFind 查询UPF总流量 N3上行 N6下行
// day 统计天数
// down * 8 / 1000 / 1000 单位M
// down / 1000 / 1000 单位M
func (r KpiReport) UPFTodayFlowFind(neUid string, day int) (int64, int64) {
// 获取当前日期
now := time.Now()
@@ -280,3 +280,72 @@ func (r KpiReport) UPFTodayFlowLoad(day int) {
}
}
}
// IMSBusyHour IMS忙时流量统计
// SCSCF.06呼叫尝试次数 SCSCF.09呼叫成功次数
func (r KpiReport) IMSBusyHour(coreUid string, neUid string, timestamp int64) []map[string]any {
t := time.UnixMilli(timestamp)
beginTime := t
endTime := t
// 检查时分秒是否都为零
if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 {
// 获取当天起始时间00:00:00
beginTime = t.Truncate(time.Hour)
// 计算当天结束时间23:59:59
endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
} else {
// 起始时间:当前小时的 00 分 00 秒
beginTime = t.Truncate(time.Hour)
// 结束时间:当前小时的 59 分 59 秒 999 毫秒
endTime = beginTime.Add(time.Hour - time.Millisecond)
}
// 转换为毫秒级时间戳
rows := r.kpiReportRepository.SelectIMS(coreUid, neUid, beginTime.UnixMilli(), endTime.UnixMilli())
// 创建一个map来存储按时间段合并后的数据
timeGroup := make(map[int64]map[string]int64)
// 遍历每个数据项
for _, row := range rows {
// 将毫秒时间戳转换为小时级时间戳(保留到小时的起始毫秒)
timeHour := row.CreatedAt / 3600000 * 3600000 // 1小时 = 3600000毫秒
// 解析 JSON 字符串为 map
var kpiValues []map[string]any
err := json.Unmarshal([]byte(row.KpiValues), &kpiValues)
if err != nil {
continue
}
var callAttempts, callCompletions int64
for _, v := range kpiValues {
if k, ok := v["kpiId"]; ok {
if k == "SCSCF.06" {
callAttempts = parse.Number(v["value"])
}
if k == "SCSCF.09" {
callCompletions = parse.Number(v["value"])
}
}
}
// 合并到对应的小时段
if _, exists := timeGroup[timeHour]; !exists {
timeGroup[timeHour] = map[string]int64{
"callAttempts": 0,
"callCompletions": 0,
}
}
timeGroup[timeHour]["callAttempts"] += callAttempts
timeGroup[timeHour]["callCompletions"] += callCompletions
}
// 时间组合输出
data := make([]map[string]any, 0, len(timeGroup))
for hour, sums := range timeGroup {
data = append(data, map[string]any{
"timeGroup": fmt.Sprintf("%d", hour),
"callAttempts": sums["callAttempts"],
"callCompletions": sums["callCompletions"],
})
}
return data
}

View File

@@ -4,8 +4,10 @@ import (
"fmt"
"strconv"
"strings"
"time"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/utils/date"
neService "be.ems/src/modules/ne/service"
"be.ems/src/modules/ne_data/model"
"be.ems/src/modules/ne_data/repository"
@@ -63,15 +65,25 @@ func (r *UDMAuthUser) dataByRedis(coreUid, neUid, imsi string) []model.UDMAuthUs
if v, ok := m["amf"]; ok {
amf = strings.Replace(v, "\r\n", "", 1)
}
// 创建时间
var createTime int64 = 0
if v, ok := m["create_time"]; ok {
t := date.ParseStrToDate(v, time.RFC3339)
createTime = t.UnixMilli()
} else {
createTime = time.Now().UnixMilli()
}
a := model.UDMAuthUser{
CoreUID: coreUid,
NeUID: neUid,
NeType: "UDM",
IMSI: imsi,
Amf: amf,
Ki: m["ki"],
AlgoIndex: m["algo"],
Opc: m["opc"],
CoreUID: coreUid,
NeUID: neUid,
NeType: "UDM",
IMSI: imsi,
Amf: amf,
Ki: m["ki"],
AlgoIndex: m["algo"],
Opc: m["opc"],
CreateTime: createTime,
}
arr = append(arr, a)
}