package service import ( "errors" "fmt" "github.com/jinzhu/copier" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "sort" "xorm.io/xorm" ) type AlertClassSvc struct { User entity.SystemUserInfo } func (a *AlertClassSvc) Add(session *xorm.Session, req request.AddAlertClass) (classId int, err error) { now := jsontime.Now() data := entity.AlertClass{ CreatedBy: a.User.SystemAccount, CreatedAt: now, UpdatedBy: a.User.SystemAccount, UpdatedAt: now, } if req.Source != constant.SourceCustom { req.Source = constant.SourceDefault } _ = copier.Copy(&data, &req) var max int if data.SortOrder >= 0 { max, err = a.SortOrderMax(data.ParentId) if err != nil { return } data.SortOrder = max + 1 } _, err = session.Insert(&data) classId = data.ClassId return } func (a *AlertClassSvc) Update(session *xorm.Session, req request.UpdateAlertClass) error { now := jsontime.Now() data := entity.AlertClass{ UpdatedBy: a.User.SystemAccount, UpdatedAt: now, } _ = copier.Copy(&data, &req) _, err := session.Cols("parent_id", "class_name", "updated_by", "updated_at").ID(data.ClassId).Update(&data) if err != nil { return err } return nil } func (a *AlertClassSvc) Move(req request.MoveAlertClass) (err error) { db, err := client.GetDbClient() if err != nil { err = resp.DbConnectError.WithError(err) return err } now := jsontime.Now() data := entity.AlertClass{} _ = copier.Copy(&data, &req) var list []entity.AlertClass _, err = db.NewSession().Where("class_id = ?", req.ClassId).Get(&data) err = db.NewSession().Where("parent_id = ?", data.ParentId).Where("source = 1").OrderBy("sort_order asc").Find(&list) var previousIndex int var nextIndex int for i := 0; i < len(list); i++ { if list[i].ClassId == req.ClassId { previousIndex = i - 1 nextIndex = i + 1 break } } var ( mover entity.AlertClass moved entity.AlertClass ) switch req.Direction { case "up": if previousIndex < 0 { err = errors.New("top data cannot be moved") return } list[previousIndex].SortOrder, list[previousIndex+1].SortOrder = list[previousIndex+1].SortOrder, list[previousIndex].SortOrder mover, moved = list[previousIndex+1], list[previousIndex] case "down": if nextIndex > len(list)-1 { err = errors.New("bottom data cannot be moved") return } list[nextIndex-1].SortOrder, list[nextIndex].SortOrder = list[nextIndex].SortOrder, list[nextIndex-1].SortOrder mover, moved = list[nextIndex-1], list[nextIndex] } mover.UpdatedBy, moved.UpdatedBy = "", "" mover.UpdatedAt, moved.UpdatedAt = now, now session := db.NewSession() defer session.Close() err = session.Begin() _, err = session.Cols("sort_order", "updated_by", "updated_at").ID(mover.ClassId).Update(&mover) if err != nil { err = session.Rollback() return } _, err = session.Cols("sort_order", "updated_by", "updated_at").ID(moved.ClassId).Update(&moved) if err != nil { err = session.Rollback() return } err = session.Commit() if err != nil { return } return nil } func (a *AlertClassSvc) GetDataById(req request.DetailAlertClass) (resp response.AlertClassItem, err error) { db, err := client.GetDbClient() if err != nil { return } _, err = db.NewSession().Table(resp.TableName()).ID(req.ClassId).Get(&resp) return } func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertClassList, err error) { db, err := client.GetDbClient() if err != nil { return } session := db.NewSession() defer session.Close() session.Where("source = 1") if req.ClassId != 0 { session.Where("class_id = ?", req.ClassId) } if req.ClassName != "" { session.Where("class_name LIKE ?", "%"+req.ClassName+"%") } if req.Page == -1 { req.PageSize = 100000 } resp.TotalCount, err = session.Limit(req.GetPageSize(), (req.GetPage()-1)*req.GetPageSize()). OrderBy("sort_order").FindAndCount(&resp.List) return } func (a *AlertClassSvc) AlertObjectList() (resp response.AlertClassList, err error) { db, err := client.GetDbClient() if err != nil { return } session := db.NewSession() defer session.Close() session.Where("parent_id <> 0") resp.TotalCount, err = session.OrderBy("sort_order").FindAndCount(&resp.List) return } func (a *AlertClassSvc) Tree(req request.ListAlertClass) (resp []*response.AlertClassNode, err error) { db, err := client.GetDbClient() if err != nil { return } session := db.NewSession() defer session.Close() var list []entity.AlertClass session.Where("source = 1") _, err = session.OrderBy("sort_order").FindAndCount(&list) // TODO 对req进行过滤 resp, err = AlertClassTree(list) return } func AlertClassTree(nodes []entity.AlertClass) ([]*response.AlertClassNode, error) { nodeMap := make(map[int]*response.AlertClassNode) // 创建所有节点并存储到映射表中 for _, node := range nodes { tree := &response.AlertClassNode{ AlertClass: node, Children: []*response.AlertClassNode{}, } nodeMap[node.ClassId] = tree } var rootNodes []*response.AlertClassNode for _, node := range nodes { if node.ParentId == 0 { rootNodes = append(rootNodes, nodeMap[node.ClassId]) } else { parent := nodeMap[node.ParentId] if parent == nil { return nil, fmt.Errorf("parent node not found for ClassId: %d", node.ClassId) } parent.Children = append(parent.Children, nodeMap[node.ClassId]) } } sortTree(rootNodes) return rootNodes, nil } func sortTree(nodes []*response.AlertClassNode) { sort.Slice(nodes, func(i, j int) bool { return nodes[i].SortOrder < nodes[j].SortOrder }) for _, node := range nodes { sortTree(node.Children) } } func (a *AlertClassSvc) SortOrderMax(parentId int) (max int, err error) { db, err := client.GetDbClient() if err != nil { return } _, err = db.NewSession().Table(new(entity.AlertClass)). Select("max(sort_order)"). Where("parent_id = ?", parentId).Where("source = 1").Get(&max) return } func (a *AlertClassSvc) Delete(ids []int) (err error) { db, err := client.GetDbClient() if err != nil { return err } var classes []entity.AlertClass err = db.In("class_id", ids).Find(&classes) // 检查是否所有指定的 ids 都存在于数据库中 if len(ids) > len(classes) { return errors.New("部分数据不存在") } var notExist []int idSet := make(map[int]bool) for _, v := range classes { idSet[v.ClassId] = true } for _, id := range ids { if !idSet[id] { notExist = append(notExist, id) } } if len(notExist) > 0 { return errors.New(fmt.Sprintf("指标分类或对象id为%v的数据未查询到", notExist)) } for _, v := range classes { if v.ParentId == 0 { // 如果是父级数据,判断是否存在子集 var num int has, err := db.Table(new(entity.AlertClass)).Select("count(*)").Where("parent_id = ?", v.ClassId).Get(&num) if err != nil { return err } if has && num > 0 { return errors.New("当前分类存在指标对象子集数据,不允许删除") } } else { // 如果为子集数据,判断是否存在指标配置关联 var configCount int has, err := db.Table(new(entity.MetricConfig)).Select("count(*)").Where("class_id = ?", v.ClassId).Get(&configCount) if err != nil { return err } if has && configCount > 0 { return errors.New("指标对象存在指标配置关联,不允许删除") } } // 删除数据 _, err = db.ID(v.ClassId).Delete(v) if err != nil { return err } } return nil }