package data import ( "eta/eta_api/models" "eta/eta_api/utils" "fmt" "strconv" "strings" "time" ) func CommonClassifyMove(req models.CommonClassifyMoveReq, strategy CommonClassifyStrategy) (tips string, err error) { ctx := NewCommonClassifyCtx(strategy) var ( classify *models.CommonClassify parentClassify *models.CommonClassify prevClassify *models.CommonClassify nextClassify *models.CommonClassify object *models.CommonClassifyObj prevObject *models.CommonClassifyObj nextObject *models.CommonClassifyObj sortPrev int sortNext int ) // 获取父级分类 if req.ParentClassifyId > 0 { c, e := ctx.GetCommonClassifyById(req.ParentClassifyId) if e != nil { err = fmt.Errorf("获取上级分类失败, %v", e) return } parentClassify = c } // 兄弟节点 if req.PrevClassifyId > 0 { c, e := ctx.GetCommonClassifyById(req.PrevClassifyId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "上一个分类不存在, 请刷新页面" return } err = fmt.Errorf("获取上一个分类失败, %v", e) return } prevClassify = c sortPrev = prevClassify.Sort } else if req.PrevObjectId > 0 { obj, e := ctx.GetObjectById(req.PrevObjectId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "上一个移动对象不存在, 请刷新页面" return } err = fmt.Errorf("获取上一个移动对象失败, %v", e) return } prevObject = obj sortPrev = prevObject.Sort } if req.NextClassifyId > 0 { c, e := ctx.GetCommonClassifyById(req.NextClassifyId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "下一个分类不存在, 请刷新页面" return } err = fmt.Errorf("获取下一个分类失败, %v", e) return } nextClassify = c sortNext = nextClassify.Sort } else if req.NextObjectId > 0 { obj, e := ctx.GetObjectById(req.NextObjectId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "下一个移动对象不存在, 请刷新页面" return } err = fmt.Errorf("获取下一个移动对象失败, %v", e) return } nextObject = obj sortNext = nextObject.Sort } // 移动分类 if req.ObjectId == 0 { c, e := ctx.GetCommonClassifyById(req.ClassifyId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "当前分类不存在, 请刷新页面" return } err = fmt.Errorf("获取当前分类失败, %v", e) return } classify = c return moveCommonClassify(ctx, req, classify, parentClassify, prevClassify, nextClassify, prevObject, nextObject, sortPrev, sortNext) } // 移动对象 if req.ObjectId > 0 { obj, e := ctx.GetObjectById(req.ObjectId) if e != nil { if e.Error() == utils.ErrNoRow() { tips = "移动对象不存在, 请刷新页面" return } err = fmt.Errorf("获取移动对象失败, %v", e) return } if req.ParentClassifyId <= 0 { tips = "移动对象必须挂在分类下" return } object = obj // TODO:对象的不同实现, 如指标校验权限 return moveCommonClassifyObj(ctx, req, prevClassify, nextClassify, object, prevObject, nextObject, sortPrev, sortNext) } return } func moveCommonClassify(ctx *CommonClassifyCtx, req models.CommonClassifyMoveReq, classify, parentClassify, prevClassify, nextClassify *models.CommonClassify, prevObject, nextObject *models.CommonClassifyObj, sortPrev, sortNext int) (tips string, err error) { // 校验层级以及父级分类下同名分类 if req.ParentClassifyId > 0 && parentClassify.Level == 6 { tips = "最高只支持添加6级分类" return } exists, e := ctx.GetClassifyByParentIdAndName(req.ParentClassifyId, classify.ClassifyName, classify.ClassifyId) if e != nil && e.Error() != utils.ErrNoRow() { err = fmt.Errorf("获取父级分类下的同名分类失败, %v", e) return } if exists != nil { tips = "当前父级分类下存在相同名称" return } // TODO:分类的非通用实现, 如指标分类需校验权限, 可以采用适配器模式兼容进来 var classifyChildIds []int var classifyUpdateCols []string originParentId := classify.ParentId originLevel := classify.Level // 需更新子层级分类ID if originParentId != req.ParentClassifyId { // TODO:此处如果要兼容以前的分类表, 那么要提出来处理 levelPathArr := strings.Split(classify.LevelPath, ",") for _, p := range levelPathArr { d, _ := strconv.Atoi(p) if d > 0 { classifyChildIds = append(classifyChildIds, d) } } } colsMapping := ctx.GetCommonClassifyCols() // 分类表实际的字段映射 // 判断上级ID是否一致, 不一致的话需要移动该分类层级 if classify.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 { if classify.Level != parentClassify.Level+1 { //禁止层级调整 tips = "不支持目录层级变更" return } classify.ParentId = parentClassify.ClassifyId classify.RootId = parentClassify.RootId classify.Level = parentClassify.Level + 1 classify.ModifyTime = time.Now() classifyUpdateCols = append(classifyUpdateCols, colsMapping.ParentId, colsMapping.RootId, colsMapping.Level, colsMapping.ModifyTime) } if classify.ParentId != req.ParentClassifyId && req.ParentClassifyId == 0 { tips = "不支持目录层级变更" return } if sortPrev > 0 { // 移动至两个兄弟之间 if sortNext > 0 { // 如果上一个兄弟与下一个兄弟的排序权重是一致的, 那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2, 自己变成上一个兄弟的排序权重+1 if sortPrev == sortNext || sortPrev == classify.Sort { sortUpdate := `sort + 2` if prevClassify != nil { if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, sortUpdate, e) return } } else { if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, sortPrev, sortUpdate, e) return } } if prevObject != nil { if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate, e) return } } else { if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, 0, sortUpdate, e) return } } } else { // 如果下一个兄弟的排序权重正好是上个兄弟节点的下一层, 那么需要再加一层 if sortNext-sortPrev == 1 { sortUpdate := `sort + 1` if prevClassify != nil { if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, prevClassify.ClassifyId, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, prevClassify.ClassifyId, sortPrev, sortUpdate, e) return } } else { if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, sortPrev, sortUpdate, e) return } } if prevObject != nil { if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate, e) return } } else { if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, 0, sortUpdate, e) return } } } } } classify.Sort = sortPrev + 1 classify.ModifyTime = time.Now() classifyUpdateCols = append(classifyUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } else if prevClassify == nil && nextClassify == nil && prevObject == nil && nextObject == nil && req.ParentClassifyId > 0 { // 处理只拖动到目录里, 默认放到目录底部的情况 m, e := GetCommonClassifySortMaxByParentId(req.ParentClassifyId, ctx) if e != nil { err = fmt.Errorf("GetCommonClassifySortMaxByParentId, %v", e) return } classify.Sort = m + 1 classify.ModifyTime = time.Now() classifyUpdateCols = append(classifyUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } else { // 拖动到父级分类的第一位 firstClassify, e := ctx.GetFirstClassifyByParentId(req.ParentClassifyId) if e != nil && e.Error() != utils.ErrNoRow() { //tips = "移动失败" err = fmt.Errorf("GetFirstClassifyByParentId, %v", e) return } // 如果该分类下存在其他分类, 且第一个其他分类的排序等于0, 那么需要调整排序 if firstClassify != nil && firstClassify.Sort == 0 { sortUpdate := ` sort + 1 ` if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, firstClassify.ClassifyId-1, 0, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, firstClassify.ClassifyId-1, 0, sortUpdate, e) return } // 该分类下的所有指标也需要+1 if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, 0, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, 0, sortUpdate, e) return } } else { // 如果该分类下存在指标, 且第一个指标的排序等于0, 那么需要调整排序 firstObject, e := ctx.GetFirstObjectByClassifyId(req.ParentClassifyId) if e != nil && e.Error() != utils.ErrNoRow() { err = fmt.Errorf("GetFirstObjectByClassifyId, %v", e) return } //如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序 if firstObject != nil && firstObject.Sort == 0 { sortUpdate := ` sort + 1 ` if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, 0, firstObject.ObjectId-1, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, firstObject.ObjectId-1, sortUpdate, e) return } if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, 0, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, 0, sortUpdate, e) return } } } classify.Sort = 0 // 那就是排在第一位 classify.ModifyTime = time.Now() classifyUpdateCols = append(classifyUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } // 更新分类 if len(classifyUpdateCols) > 0 { if e = ctx.UpdateCommonClassify(classify, classifyUpdateCols); e != nil { err = fmt.Errorf("UpdateCommonClassify, %v", e) return } // 更新对应分类的root_id和层级 if originParentId != req.ParentClassifyId { if len(classifyChildIds) > 0 { stepLevel := classify.Level - originLevel if e = ctx.UpdateClassifyChildByParentId(classifyChildIds, classify.RootId, stepLevel); e != nil { err = fmt.Errorf("UpdateClassifyChildByParentId, parentId: %d, classifyId: %d, stepLevel: %d, err: %v", req.ParentClassifyId, classify.ClassifyId, stepLevel, e) return } } } } return } func moveCommonClassifyObj(ctx *CommonClassifyCtx, req models.CommonClassifyMoveReq, prevClassify, nextClassify *models.CommonClassify, object, prevObject, nextObject *models.CommonClassifyObj, sortPrev, sortNext int) (tips string, err error) { var objUpdateCols []string colsMapping := ctx.GetCommonClassifyObjCols() // 分类对象表实际的字段映射 // 分类变更的情况 if object.ClassifyId != req.ParentClassifyId { object.ClassifyId = req.ParentClassifyId object.ModifyTime = time.Now() objUpdateCols = append(objUpdateCols, colsMapping.ClassifyId, colsMapping.ModifyTime) } if sortPrev > 0 { // 移动至两个兄弟之间 if sortNext > 0 { // 如果上一个兄弟与下一个兄弟的排序权重是一致的, 那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2, 自己变成上一个兄弟的排序权重+1 if sortPrev == sortNext || sortPrev == object.Sort { sortUpdate := `sort + 2` if prevClassify != nil { if e := ctx.SetClassifySortByParentId(req.ParentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, sortUpdate, e) return } } else { if e := ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, sortPrev, sortUpdate, e) return } } if prevObject != nil { if e := ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate, e) return } } else { if e := ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, 0, sortUpdate, e) return } } } else { // 如果下一个兄弟的排序权重正好是上个兄弟节点的下一层, 那么需要再加一层 if sortNext-sortPrev == 1 { sortUpdate := `sort + 1` if prevClassify != nil { if e := ctx.SetClassifySortByParentId(req.ParentClassifyId, prevClassify.ClassifyId, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, prevClassify.ClassifyId, sortPrev, sortUpdate, e) return } } else { if e := ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, sortPrev, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, sortPrev, sortUpdate, e) return } } if prevObject != nil { if e := ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, prevObject.ObjectId, sortUpdate, e) return } } else { if e := ctx.SetObjectSortByClassifyId(req.ParentClassifyId, sortPrev, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, sortPrev, 0, sortUpdate, e) return } } } } } object.Sort = sortPrev + 1 object.ModifyTime = time.Now() objUpdateCols = append(objUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } else if prevClassify == nil && nextClassify == nil && prevObject == nil && nextObject == nil && req.ParentClassifyId > 0 { // 处理只拖动到目录里, 默认放到目录底部的情况 m, e := GetCommonClassifySortMaxByParentId(req.ParentClassifyId, ctx) if e != nil { err = fmt.Errorf("GetCommonClassifySortMaxByParentId, %v", e) return } object.Sort = m + 1 //那就是排在组内最后一位 object.ModifyTime = time.Now() objUpdateCols = append(objUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } else { // 拖动到父级分类的第一位 firstClassify, e := ctx.GetFirstClassifyByParentId(req.ParentClassifyId) if e != nil && e.Error() != utils.ErrNoRow() { err = fmt.Errorf("GetFirstClassifyByParentId, %v", e) return } // 如果该分类下存在其他分类, 且第一个其他分类的排序等于0, 那么需要调整排序 if firstClassify != nil && firstClassify.Sort == 0 { sortUpdate := ` sort + 1 ` if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, firstClassify.ClassifyId-1, 0, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, firstClassify.ClassifyId-1, 0, sortUpdate, e) return } // 该分类下的所有指标也需要+1 if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, 0, 0, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, 0, sortUpdate, e) return } } else { // 如果该分类下存在对象, 且第一个对象的排序等于0, 那么需要调整排序 firstObject, e := ctx.GetFirstObjectByClassifyId(req.ParentClassifyId) if e != nil && e.Error() != utils.ErrNoRow() { err = fmt.Errorf("GetFirstObjectByClassifyId, %v", e) return } // 如果该分类下存在其他分类, 且第一个其他分类的排序等于0, 那么需要调整排序 if firstObject != nil && firstObject.Sort == 0 { sortUpdate := ` sort + 1 ` if e = ctx.SetObjectSortByClassifyId(req.ParentClassifyId, 0, firstObject.ObjectId-1, sortUpdate); e != nil { err = fmt.Errorf("SetObjectSortByClassifyId, classifyId: %d, sort: %d, objectId: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, firstObject.ObjectId-1, sortUpdate, e) return } if e = ctx.SetClassifySortByParentId(req.ParentClassifyId, 0, 0, sortUpdate); e != nil { err = fmt.Errorf("SetClassifySortByParentId, parentId: %d, classifyId: %d, sort: %d, sortUpdate: %s, err: %v", req.ParentClassifyId, 0, 0, sortUpdate, e) return } } } object.Sort = 0 // 那就是排在第一位 object.ModifyTime = time.Now() objUpdateCols = append(objUpdateCols, colsMapping.Sort, colsMapping.ModifyTime) } // 更新分类对象 if len(objUpdateCols) > 0 { if e := ctx.UpdateCommonClassifyObj(object, objUpdateCols); e != nil { err = fmt.Errorf("UpdateCommonClassifyObj, %v", e) return } } return } // GetCommonClassifySortMaxByParentId 获取分类下最大排序 func GetCommonClassifySortMaxByParentId(parentId int, ctx *CommonClassifyCtx) (sortMax int, err error) { // 比对分类和对象的最大排序 classifyMax, e := ctx.GetClassifySortMaxByParentId(parentId) if e != nil { err = fmt.Errorf("GetClassifySortMaxByParentId, %v", e) return } sortMax = classifyMax objectMax, e := ctx.GetObjectSortMaxByClassifyId(parentId) if e != nil { err = fmt.Errorf("GetObjectSortMaxByClassifyId, %v", e) return } if sortMax < objectMax { sortMax = objectMax } return }