From 289e892254fb4ef00e507f836538cefb0398b93c Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Fri, 15 Sep 2023 18:01:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20UDM=E5=AF=BC=E5=85=A5txt=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/udm_user/api_udm_user.go | 35 +++++++++++++------ features/udm_user/repo/repo_udm_auth_user.go | 7 +++- features/udm_user/repo/repo_udm_sub_user.go | 16 +++++++-- .../udm_user/service/service_udm_auth_user.go | 24 ++++++++++++- .../udm_user/service/service_udm_sub_user.go | 29 ++++++++++++++- 5 files changed, 96 insertions(+), 15 deletions(-) diff --git a/features/udm_user/api_udm_user.go b/features/udm_user/api_udm_user.go index 2bdda4d4..e31a5eea 100644 --- a/features/udm_user/api_udm_user.go +++ b/features/udm_user/api_udm_user.go @@ -520,8 +520,8 @@ func (s *UdmUserApi) UdmAuthUserImport(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.ErrMsg(err.Error())) return } - if !strings.HasSuffix(fileHeader.Filename, ".csv") { - ctx.JSON(w, 200, result.ErrMsg("请上传CSV格式文件,内容字段imsi, ki, algo, amf, opc")) + if !(strings.HasSuffix(fileHeader.Filename, ".csv") || strings.HasSuffix(fileHeader.Filename, ".txt")) { + ctx.JSON(w, 200, result.ErrMsg("请上传.csv、.txt格式文件,内容字段imsi,ki,algo,amf,opc")) return } @@ -557,11 +557,19 @@ func (s *UdmUserApi) UdmAuthUserImport(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.ErrMsg(err.Error())) return } + // 命令ok时 if strings.Contains(data, "ok") { - data := file.ReadCSVFile(filePath) - neId = "-" - s.authUser.InsertCSV(neId, data) + if strings.HasSuffix(fileHeader.Filename, ".csv") { + data := file.ReadCSVFile(filePath) + neId = "-" + s.authUser.InsertCSV(neId, data) + } + if strings.HasSuffix(fileHeader.Filename, ".txt") { + data := file.ReadTxtFile(filePath) + neId = "-" + s.authUser.InsertTxt(neId, data) + } } ctx.JSON(w, 200, result.OkData(data)) } @@ -1048,8 +1056,8 @@ func (s *UdmUserApi) UdmSubUserImport(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.ErrMsg(err.Error())) return } - if !strings.HasSuffix(fileHeader.Filename, ".csv") { - ctx.JSON(w, 200, result.ErrMsg("请上传CSV格式文件,内容字段imsi, msisdn, ambr, nssai, arfb, sar,rat, cn, smf_sel, sm_dat,eps_dat")) + if !(strings.HasSuffix(fileHeader.Filename, ".csv") || strings.HasSuffix(fileHeader.Filename, ".txt")) { + ctx.JSON(w, 200, result.ErrMsg("请上传.csv、.txt格式文件,内容字段imsi,msisdn,ambr,nssai,arfb,sar,rat,cn,smf_sel,sm_dat,eps_dat")) return } @@ -1087,9 +1095,16 @@ func (s *UdmUserApi) UdmSubUserImport(w http.ResponseWriter, r *http.Request) { } // 命令ok时 if strings.Contains(data, "ok") { - data := file.ReadCSVFile(filePath) - neId = "-" - s.subUser.InsertCSV(neId, data) + if strings.HasSuffix(fileHeader.Filename, ".csv") { + data := file.ReadCSVFile(filePath) + neId = "-" + s.subUser.InsertCSV(neId, data) + } + if strings.HasSuffix(fileHeader.Filename, ".txt") { + data := file.ReadTxtFile(filePath) + neId = "-" + s.subUser.InsertTxt(neId, data) + } } ctx.JSON(w, 200, result.OkData(data)) } diff --git a/features/udm_user/repo/repo_udm_auth_user.go b/features/udm_user/repo/repo_udm_auth_user.go index e20f373a..6b836b8c 100644 --- a/features/udm_user/repo/repo_udm_auth_user.go +++ b/features/udm_user/repo/repo_udm_auth_user.go @@ -195,6 +195,7 @@ func (r *RepoUdmAuthUser) Insert(neID string, authUser model.UdmAuthUser) int64 func (r *RepoUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num string) int64 { var insertNum int64 + imsiVlen := len(authUser.Imsi) imsiV, err := strconv.Atoi(authUser.Imsi) if err != nil { return 0 @@ -208,7 +209,11 @@ func (r *RepoUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num s authUser.NeID = neID authUser.Status = "1" for i := 0; i < numV; i++ { - authUser.Imsi = fmt.Sprint(imsiV + i) + imsi := fmt.Sprint(imsiV + i) + if len(imsi) < imsiVlen { + imsi = fmt.Sprintf("%0*s", imsiVlen, imsi) + } + authUser.Imsi = imsi results, err := datasource.DefaultDB().Table("u_auth_user").Insert(authUser) if err == nil { insertNum += results diff --git a/features/udm_user/repo/repo_udm_sub_user.go b/features/udm_user/repo/repo_udm_sub_user.go index 53e13585..1af3902d 100644 --- a/features/udm_user/repo/repo_udm_sub_user.go +++ b/features/udm_user/repo/repo_udm_sub_user.go @@ -210,10 +210,12 @@ func (r *RepoUdmSubUser) Insert(neID string, subUser model.UdmSubUser) int64 { func (r *RepoUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num string) int64 { var insertNum int64 + imsiVlen := len(subUser.Imsi) imsiV, err := strconv.Atoi(subUser.Imsi) if err != nil { return 0 } + msisdnVlen := len(subUser.Msisdn) msisdnV, err := strconv.Atoi(subUser.Msisdn) if err != nil { return 0 @@ -226,8 +228,18 @@ func (r *RepoUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num stri subUser.NeID = neID for i := 0; i < numV; i++ { - subUser.Imsi = fmt.Sprint(imsiV + i) - subUser.Msisdn = fmt.Sprint(msisdnV + i) + msisdn := fmt.Sprint(msisdnV + i) + if len(msisdn) < msisdnVlen { + msisdn = fmt.Sprintf("%0*s", msisdnVlen, msisdn) + } + subUser.Msisdn = msisdn + + imsi := fmt.Sprint(imsiV + i) + if len(imsi) < imsiVlen { + imsi = fmt.Sprintf("%0*s", imsiVlen, imsi) + } + subUser.Imsi = imsi + // IP会自动递增 if subUser.StaticIp != "" { parts := strings.Split(subUser.StaticIp, ".") diff --git a/features/udm_user/service/service_udm_auth_user.go b/features/udm_user/service/service_udm_auth_user.go index c6651ba8..c8c7a4d0 100644 --- a/features/udm_user/service/service_udm_auth_user.go +++ b/features/udm_user/service/service_udm_auth_user.go @@ -47,7 +47,7 @@ func (r *ServiceUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, nu return r.repoAuthUser.Inserts(neID, authUser, num) } -// Insert UDM鉴权用户-批量添加 +// InsertCSV UDM鉴权用户-批量添加 func (r *ServiceUdmAuthUser) InsertCSV(neID string, data []map[string]string) int64 { var num int64 for _, v := range data { @@ -74,6 +74,28 @@ func (r *ServiceUdmAuthUser) InsertCSV(neID string, data []map[string]string) in return num } +// InsertTxt UDM鉴权用户-批量添加 +func (r *ServiceUdmAuthUser) InsertTxt(neID string, data [][]string) int64 { + var num int64 + for _, v := range data { + if len(v) < 4 { + continue + } + var authUser model.UdmAuthUser + authUser.NeID = neID + authUser.Status = "1" + authUser.Imsi = v[0] + authUser.Ki = v[1] + authUser.AlgoIndex = v[2] + authUser.Amf = v[3] + if len(v) == 5 { + authUser.Opc = v[4] + } + num += r.repoAuthUser.Insert(neID, authUser) + } + return num +} + // Insert UDM鉴权用户-修改更新 func (r *ServiceUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 { return r.repoAuthUser.Update(neID, authUser) diff --git a/features/udm_user/service/service_udm_sub_user.go b/features/udm_user/service/service_udm_sub_user.go index f265eacf..5cc29d57 100644 --- a/features/udm_user/service/service_udm_sub_user.go +++ b/features/udm_user/service/service_udm_sub_user.go @@ -47,7 +47,7 @@ func (r *ServiceUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num s return r.repoSunUser.Inserts(neID, subUser, num) } -// Insert UDM签约用户-批量添加 +// InsertCSV UDM签约用户-批量添加 func (r *ServiceUdmSubUser) InsertCSV(neID string, data []map[string]string) int64 { var num int64 for _, v := range data { @@ -91,6 +91,33 @@ func (r *ServiceUdmSubUser) InsertCSV(neID string, data []map[string]string) int return num } +// InsertTxt UDM签约用户-批量添加 +func (r *ServiceUdmSubUser) InsertTxt(neID string, data [][]string) int64 { + var num int64 + for _, v := range data { + if len(v) < 10 { + continue + } + var subUser model.UdmSubUser + subUser.NeID = neID + subUser.Imsi = v[0] + subUser.Msisdn = v[1] + subUser.Ambr = v[2] + subUser.Nssai = v[3] + subUser.Arfb = v[4] + subUser.Sar = v[5] + subUser.Rat = v[6] + subUser.Cn = v[7] + subUser.SmfSel = v[8] + subUser.SmData = v[9] + if len(v) == 11 { + subUser.EpsDat = v[10] + } + num += r.repoSunUser.Insert(neID, subUser) + } + return num +} + // Insert UDM签约用户-批量添加4G用户 func (r *ServiceUdmSubUser) Insert4G(neID string, subUser model.UdmSubUser) int64 { return r.repoSunUser.Insert4G(neID, subUser) From 3b761cd3f35c9d8347d43aec59ff2e9b5b9cbc04 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Fri, 15 Sep 2023 18:02:09 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20mml=E6=8C=87=E4=BB=A4=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E5=88=A4=E6=96=ADok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/mml_client/send.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/mml_client/send.go b/lib/core/mml_client/send.go index b8dc531a..7e225798 100644 --- a/lib/core/mml_client/send.go +++ b/lib/core/mml_client/send.go @@ -42,14 +42,14 @@ func MMLSendMsgToString(ip, msg string) (string, error) { } // 截断 - index := strings.Index(str, "\nUDM>") + index := strings.Index(str, "\n") if index != -1 { str = str[:index] str = strings.ToLower(str) } // 命令成功 - if strings.Contains(str, "ok") { + if strings.Contains(str, "ok") || strings.Contains(str, "OK") { return str, nil } From 9e0ff2733acbfa2ee44418fc9f967daf8e8a20c7 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Fri, 15 Sep 2023 18:23:24 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20UDM=E5=AF=BC=E5=87=BAcsv=E5=92=8Ctxt?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/udm_user/api_udm_user.go | 138 +++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 41 deletions(-) diff --git a/features/udm_user/api_udm_user.go b/features/udm_user/api_udm_user.go index e31a5eea..4c5cb93f 100644 --- a/features/udm_user/api_udm_user.go +++ b/features/udm_user/api_udm_user.go @@ -80,10 +80,10 @@ func Routers() []services.RouterItem { Middleware: midware.Authorize(nil), }, { - Method: "POST", - Pattern: "/authExport/{neId}", - Handler: apis.UdmAuthUserExport, - Middleware: midware.Authorize(nil), + Method: "POST", + Pattern: "/authExport", + Handler: apis.UdmAuthUserExport, + // Middleware: midware.Authorize(nil), }, { Method: "POST", @@ -154,7 +154,7 @@ func Routers() []services.RouterItem { }, { Method: "POST", - Pattern: "/subExport/{neId}", + Pattern: "/subExport", Handler: apis.UdmSubUserExport, Middleware: midware.Authorize(nil), }, @@ -477,30 +477,58 @@ func (s *UdmUserApi) UdmAuthUserRemoves(w http.ResponseWriter, r *http.Request) // UDM鉴权用户-导出 // -// POST /authExport/{neId} +// POST /authExport func (s *UdmUserApi) UdmAuthUserExport(w http.ResponseWriter, r *http.Request) { - neId := ctx.Param(r, "neId") - if neId == "" { + var body struct { + NeId string `json:"neId"` + Type string `json:"type"` + } + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.NeId == "" || body.Type == "" { ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) return } - neId = "-" - list := s.authUser.List(model.UdmAuthUser{NeID: neId}) - // 文件名 - fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.csv", neId, time.Now().UnixMilli()) - filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName) - // 转换数据 - data := [][]string{} - data = append(data, []string{"imsi", "ki", "amf", "algo", "opc"}) - for _, v := range list { - data = append(data, []string{v.Imsi, v.Ki, v.Amf, v.AlgoIndex, v.Opc}) - } - // 输出到文件 - err := file.WriterCSVFile(data, filePath) - if err != nil { - ctx.JSON(w, 200, result.ErrMsg(err.Error())) + + if !(body.Type == "csv" || body.Type == "txt") { + ctx.JSON(w, 200, result.ErrMsg("导出文件类型支持csv、txt")) return } + + neId := "-" + list := s.authUser.List(model.UdmAuthUser{NeID: neId}) + // 文件名 + fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type) + filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName) + + if body.Type == "csv" { + // 转换数据 + data := [][]string{} + data = append(data, []string{"imsi", "ki", "amf", "algo", "opc"}) + for _, v := range list { + data = append(data, []string{v.Imsi, v.Ki, v.Amf, v.AlgoIndex, v.Opc}) + } + // 输出到文件 + err := file.WriterCSVFile(data, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + } + + if body.Type == "txt" { + // 转换数据 + data := [][]string{} + for _, v := range list { + data = append(data, []string{v.Imsi, v.Ki, v.Amf, v.AlgoIndex, v.Opc}) + } + // 输出到文件 + err = file.WriterTxtFile(data, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + } + ctx.FileAttachment(w, r, filePath, fileName) } @@ -1013,30 +1041,58 @@ func (s *UdmUserApi) UdmSubUserRemoves(w http.ResponseWriter, r *http.Request) { // UDM签约用户-导出 // -// POST /subExport/{neId} +// POST /subExport func (s *UdmUserApi) UdmSubUserExport(w http.ResponseWriter, r *http.Request) { - neId := ctx.Param(r, "neId") - if neId == "" { + var body struct { + NeId string `json:"neId"` + Type string `json:"type"` + } + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.NeId == "" || body.Type == "" { ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) return } - neId = "-" - list := s.subUser.List(model.UdmSubUser{NeID: neId}) - // 文件名 - fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.csv", neId, time.Now().UnixMilli()) - filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName) - // 转换数据 - data := [][]string{} - data = append(data, []string{"imsi", "msisdn", "ambr", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"}) - for _, v := range list { - data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, v.EpsDat}) - } - // 输出到文件 - err := file.WriterCSVFile(data, filePath) - if err != nil { - ctx.JSON(w, 200, result.ErrMsg(err.Error())) + + if !(body.Type == "csv" || body.Type == "txt") { + ctx.JSON(w, 200, result.ErrMsg("导出文件类型支持csv、txt")) return } + + neId := "-" + list := s.subUser.List(model.UdmSubUser{NeID: neId}) + // 文件名 + fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type) + filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName) + + if body.Type == "csv" { + // 转换数据 + data := [][]string{} + data = append(data, []string{"imsi", "msisdn", "ambr", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"}) + for _, v := range list { + data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, v.EpsDat}) + } + // 输出到文件 + err = file.WriterCSVFile(data, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + } + + if body.Type == "txt" { + // 转换数据 + data := [][]string{} + for _, v := range list { + data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, v.EpsDat}) + } + // 输出到文件 + err = file.WriterTxtFile(data, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + } + ctx.FileAttachment(w, r, filePath, fileName) } From 5d00ba223cf1ff6958ab063643821e9ee6eb8bf8 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Fri, 15 Sep 2023 18:25:06 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20csv=E5=92=8Ctxt=E8=AF=BB=E5=86=99?= =?UTF-8?q?=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/file/csv.go | 8 +++-- lib/core/file/txt.go | 79 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 lib/core/file/txt.go diff --git a/lib/core/file/csv.go b/lib/core/file/csv.go index f8bcce90..1473a79b 100644 --- a/lib/core/file/csv.go +++ b/lib/core/file/csv.go @@ -45,10 +45,14 @@ func WriterCSVFile(data [][]string, filePath string) error { // 读取CSV文件,转换map数据 func ReadCSVFile(filePath string) []map[string]string { + // 创建 map 存储 CSV 数据 + arr := make([]map[string]string, 0) + // 打开 CSV 文件 file, err := os.Open(filePath) if err != nil { log.Fatal("无法打开 CSV 文件:", err) + return arr } defer file.Close() @@ -59,11 +63,9 @@ func ReadCSVFile(filePath string) []map[string]string { header, err := reader.Read() if err != nil { log.Fatal("无法读取 CSV 头部行:", err) + return arr } - // 创建 map 存储 CSV 数据 - arr := make([]map[string]string, 0) - // 遍历 CSV 数据行 for { // 读取一行数据 diff --git a/lib/core/file/txt.go b/lib/core/file/txt.go new file mode 100644 index 00000000..1690e3e0 --- /dev/null +++ b/lib/core/file/txt.go @@ -0,0 +1,79 @@ +package file + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" + + "ems.agt/lib/log" +) + +// 写入Txt文件用,号分割 需要转换数据 +// 例如: +// data := [][]string{} +// data = append(data, []string{"姓名", "年龄", "城市"}) +// data = append(data, []string{"1", "2", "3"}) +// err := file.WriterCSVFile(data, filePath) +func WriterTxtFile(data [][]string, filePath string) error { + // 获取文件所在的目录路径 + dirPath := filepath.Dir(filePath) + + // 确保文件夹路径存在 + err := os.MkdirAll(dirPath, os.ModePerm) + if err != nil { + log.Errorf("创建文件夹失败 CreateFile %v", err) + } + + // 创建或打开文件 + file, err := os.Create(filePath) + if err != nil { + return err + } + defer file.Close() + + // 创建一个 Writer 对象,用于将数据写入文件 + writer := bufio.NewWriter(file) + for _, row := range data { + line := strings.Join(row, ",") + fmt.Fprintln(writer, line) + } + + // 将缓冲区中的数据刷新到文件中 + err = writer.Flush() + if err != nil { + log.Errorf("刷新缓冲区时发生错误:", err) + return err + } + return nil +} + +// 读取Txt文件,用,号分割 转换数组数据 +func ReadTxtFile(filePath string) [][]string { + // 创建 map 存储 CSV 数据 + arr := make([][]string, 0) + + // 打开文本文件 + file, err := os.Open(filePath) + if err != nil { + log.Fatal("无法打开文件:", err) + return arr + } + defer file.Close() + + // 创建一个 Scanner 对象,用于逐行读取文件内容 + scanner := bufio.NewScanner(file) + if scanner.Err() != nil { + log.Fatal("读取文件时出错:", scanner.Err()) + return arr + } + + for scanner.Scan() { + line := scanner.Text() + fields := strings.Split(line, ",") + arr = append(arr, fields) + } + + return arr +}