package service import ( "encoding/json" "fmt" "strconv" "be.ems/src/framework/logger" "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" ) // 实例化数据层 CDREventSMF 结构体 var NewCDREventSMF = &CDREventSMF{ cdrEventRepository: repository.NewCDREventSMF, } // CDREventSMF CDR会话事件SMF 服务层处理 type CDREventSMF struct { cdrEventRepository *repository.CDREventSMF // CDR会话事件数据信息 } // FindByPage 根据条件分页查询 func (r *CDREventSMF) FindByPage(querys model.CDREventSMFQuery) ([]model.CDREventSMF, int64) { return r.cdrEventRepository.SelectByPage(querys) } // DeleteByIds 批量删除信息 func (r *CDREventSMF) DeleteByIds(ids []int64) (int64, error) { // 检查是否存在 rows := r.cdrEventRepository.SelectByIds(ids) if len(rows) <= 0 { return 0, fmt.Errorf("not data") } if len(rows) == len(ids) { rows := r.cdrEventRepository.DeleteByIds(ids) return rows, nil } // 删除信息失败! return 0, fmt.Errorf("delete fail") } // ExportXlsx 导出数据到 xlsx 文件 func (r CDREventSMF) ExportXlsx(rows []model.CDREventSMF, fileName string) (string, error) { // 第一行表头标题 headerCells := map[string]string{ "A1": "ID", "B1": "Charging ID", "C1": "NE Name", "D1": "Resource Unique ID", "E1": "Subscriber ID Data", "F1": "Subscriber ID Type", "G1": "Data Volume Uplink", "H1": "Data Volume Downlink", "I1": "Data Total Volume", "J1": "Duration", "K1": "Invocation Time", "L1": "User Identifier", "M1": "SSC Mode", "N1": "DNN ID", "O1": "PDU Type", "P1": "RAT Type", "Q1": "PDU IPv4 Address", "R1": "Network Function IPv4", "S1": "PDU IPv6 Address Swith Prefix", "T1": "Record Network Function ID", "U1": "Record Type", "V1": "Record Opening Time", } // 从第二行开始的数据 dataCells := make([]map[string]any, 0) for i, row := range rows { idx := strconv.Itoa(i + 2) // 解析 JSON 字符串为 map var cdrJSON map[string]interface{} err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON) if err != nil { logger.Warnf("CDRExport Error parsing JSON: %s", err.Error()) continue } // 计费ID chargingID := "" if v, ok := cdrJSON["chargingID"]; ok && v != nil { chargingID = fmt.Sprint(parse.Number(v)) } // 订阅 ID 类型 subscriptionIDType := "-" // 订阅 ID 数据 subscriptionIDData := "-" if v, ok := cdrJSON["subscriberIdentifier"]; ok && v != nil { if sub, subOk := v.(map[string]any); subOk && sub != nil { subscriptionIDType = sub["subscriptionIDType"].(string) subscriptionIDData = sub["subscriptionIDData"].(string) } } // 网络功能 IPv4 地址 networkFunctionIPv4Address := "" if v, ok := cdrJSON["nFunctionConsumerInformation"]; ok && v != nil { if conInfo, conInfoOk := v.(map[string]any); conInfoOk && conInfo != nil { networkFunctionIPv4Address = conInfo["networkFunctionIPv4Address"].(string) } } // 数据量上行链路 var dataVolumeUplink int64 = 0 // 数据量下行链路 var dataVolumeDownlink int64 = 0 // 数据总量 var dataTotalVolume int64 = 0 if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil { usageList := v.([]any) if len(usageList) > 0 { for _, used := range usageList { usedUnit := used.(map[string]any) usedUnitList := usedUnit["usedUnitContainer"].([]any) if len(usedUnitList) > 0 { for _, data := range usedUnitList { udata := data.(map[string]any) if dup, dupOk := udata["dataVolumeUplink"]; dupOk { dataVolumeUplink += parse.Number(dup) } if ddown, ddownOk := udata["dataVolumeDownlink"]; ddownOk { dataVolumeDownlink += parse.Number(ddown) } if dt, dtOk := udata["dataTotalVolume"]; dtOk { dataTotalVolume += parse.Number(dt) } } } } } } // 时长 duration := "-" if v, ok := cdrJSON["duration"]; ok && v != nil { duration = fmt.Sprint(parse.Number(v)) } // 调用时间 invocationTimestamp := "" if v, ok := cdrJSON["invocationTimestamp"]; ok && v != nil { invocationTimestamp = v.(string) } // 记录打开时间 User_Identifier := "" SSC_Mode := "" RAT_Type := "" DNN_ID := "" PDU_Type := "" PDU_IPv4 := "" PDU_IPv6 := "" if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil { pduInfo := v.(map[string]any) if v, ok := pduInfo["userIdentifier"]; ok && v != nil { User_Identifier = v.(string) } if v, ok := pduInfo["sSCMode"]; ok && v != nil { SSC_Mode = v.(string) } if v, ok := pduInfo["rATType"]; ok && v != nil { RAT_Type = v.(string) } if v, ok := pduInfo["dNNID"]; ok && v != nil { DNN_ID = v.(string) } if v, ok := pduInfo["pDUType"]; ok && v != nil { PDU_Type = v.(string) } if v, ok := pduInfo["pDUAddress"]; ok && v != nil { pDUAddress := v.(map[string]any) if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil { PDU_IPv4 = addr.(string) } if addr, ok := pDUAddress["pDUIPv6AddresswithPrefix"]; ok && addr != nil { PDU_IPv6 = addr.(string) } } } // 记录网络参数ID recordNFID := "" if v, ok := cdrJSON["recordingNetworkFunctionID"]; ok && v != nil { recordNFID = v.(string) } //记录开始时间 recordOpeningTime := "" if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil { recordOpeningTime = v.(string) } //记录类型 recordType := "" if v, ok := cdrJSON["recordType"]; ok && v != nil { recordType = v.(string) } dataCells = append(dataCells, map[string]any{ "A" + idx: row.ID, "B" + idx: chargingID, "C" + idx: row.NeName, "D" + idx: row.RmUid, "E" + idx: subscriptionIDData, "F" + idx: subscriptionIDType, "G" + idx: dataVolumeUplink, "H" + idx: dataVolumeDownlink, "I" + idx: dataTotalVolume, "J" + idx: duration, "K" + idx: invocationTimestamp, "L" + idx: User_Identifier, "M" + idx: SSC_Mode, "N" + idx: DNN_ID, "O" + idx: PDU_Type, "P" + idx: RAT_Type, "Q" + idx: PDU_IPv4, "R" + idx: networkFunctionIPv4Address, "S" + idx: PDU_IPv6, "T" + idx: recordNFID, "U" + idx: recordType, "V" + idx: recordOpeningTime, }) } // 导出数据表格 return file.WriteSheet(headerCells, dataCells, fileName, "") }