package knowledge import ( "errors" "eta_gn/eta_api/models/knowledge" "eta_gn/eta_api/services/alarm_msg" "eta_gn/eta_api/utils" "fmt" "sort" "time" ) // MoveKnowledgeClassify 移动分类 func MoveKnowledgeClassify(req knowledge.ClassifyMoveReq) (err error, errMsg string) { knowledgeObj := new(knowledge.KnowledgeClassify) classifyId := req.ClassifyId prevClassifyId := req.PrevClassifyId nextClassifyId := req.NextClassifyId //如果有传入 上一个兄弟节点分类id var ( classifyInfo *knowledge.KnowledgeClassify prevClassify *knowledge.KnowledgeClassify nextClassify *knowledge.KnowledgeClassify prevSort int nextSort int ) // 移动对象为分类, 判断权限 classifyInfo, err = knowledgeObj.GetClassifyById(classifyId) if err != nil { if utils.IsErrNoRow(err) { errMsg = "分类不存在, 请刷新页面" err = fmt.Errorf("获取分类信息失败,Err:" + err.Error()) return } errMsg = "移动失败" err = fmt.Errorf("获取分类信息失败,Err:" + err.Error()) return } else if classifyInfo.ClassifyId == 0 { errMsg = "分类不存在, 请刷新页面" err = fmt.Errorf("获取分类信息失败") return } parentClassifyId := classifyInfo.ParentId if prevClassifyId > 0 { prevClassify, err = knowledgeObj.GetClassifyById(prevClassifyId) if err != nil { if utils.IsErrNoRow(err) { errMsg = "上一个分类不存在, 请刷新页面" err = fmt.Errorf("获取分类信息失败,Err:" + err.Error()) return } errMsg = "移动失败" err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error()) return } if prevClassify.ParentId != parentClassifyId { errMsg = "禁止拖动到其他节点" err = fmt.Errorf(errMsg) return } prevSort = prevClassify.Sort } if nextClassifyId > 0 { //下一个兄弟节点 nextClassify, err = knowledgeObj.GetClassifyById(nextClassifyId) if err != nil { if utils.IsErrNoRow(err) { errMsg = "下一个分类不存在, 请刷新页面" err = fmt.Errorf("获取分类信息失败,Err:" + err.Error()) return } errMsg = "移动失败" err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error()) return } if nextClassify.ParentId != parentClassifyId { errMsg = "禁止拖动到其他节点" err = fmt.Errorf(errMsg) return } nextSort = nextClassify.Sort } err, errMsg = moveKnowledgeClassify(classifyInfo, prevClassify, nextClassify, parentClassifyId, prevSort, nextSort, classifyInfo.ResourceType) return } // moveKnowledgeClassify 移动分类 func moveKnowledgeClassify(classifyInfo, prevClassify, nextClassify *knowledge.KnowledgeClassify, parentId, prevSort, nextSort, resourceType int) (err error, errMsg string) { knowledgeObj := new(knowledge.KnowledgeClassify) updateCol := make([]string, 0) //判断上级id是否一致,如果不一致的话,那么需要移动该分类层级 if classifyInfo.ParentId != parentId { errMsg = "移动失败" err = fmt.Errorf("不支持目录层级变更") return } if prevSort > 0 { //如果是移动在两个兄弟节点之间 if nextSort > 0 { //下一个兄弟节点 //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1 if prevSort == nextSort || prevSort == classifyInfo.Sort { //变更兄弟节点的排序 updateSortStr := `sort + 2` //变更分类 if prevClassify != nil { _ = knowledgeObj.UpdateClassifySortByParentId(parentId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr, resourceType) } else { _ = knowledgeObj.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr, resourceType) } } else { //如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了 if nextSort-prevSort == 1 { //变更兄弟节点的排序 updateSortStr := `sort + 1` //变更分类 if prevClassify != nil { _ = knowledgeObj.UpdateClassifySortByParentId(parentId, prevClassify.ClassifyId, prevSort, updateSortStr, resourceType) } else { _ = knowledgeObj.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr, resourceType) } } } } classifyInfo.Sort = prevSort + 1 classifyInfo.ModifyTime = time.Now() updateCol = append(updateCol, "Sort", "ModifyTime") } else if prevClassify == nil && nextClassify == nil && parentId > 0 { //处理只拖动到目录里,默认放到目录底部的情况 var maxSort int maxSort, err = knowledgeObj.GetMaxSortByParentId(parentId) if err != nil { errMsg = "移动失败" err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error()) return } classifyInfo.Sort = maxSort + 1 //那就是排在组内最后一位 classifyInfo.ModifyTime = time.Now() updateCol = append(updateCol, "Sort", "ModifyTime") } else { // 拖动到父级分类的第一位 firstPermission, tmpErr := knowledgeObj.GetFirstClassifyByParentId(parentId) if tmpErr != nil && !utils.IsErrNoRow(tmpErr) { errMsg = "移动失败" err = fmt.Errorf("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error()) return } //如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序 if firstPermission != nil && firstPermission.ClassifyId > 0 && firstPermission.Sort == 0 { updateSortStr := ` sort + 1 ` _ = knowledgeObj.UpdateClassifySortByParentId(parentId, firstPermission.ClassifyId-1, 0, updateSortStr, resourceType) } classifyInfo.Sort = 0 //那就是排在第一位 classifyInfo.ModifyTime = time.Now() updateCol = append(updateCol, "Sort", "ModifyTime") } //更新 if len(updateCol) > 0 { err = classifyInfo.Update(updateCol) if err != nil { errMsg = "移动失败" err = fmt.Errorf("修改失败,Err:" + err.Error()) return } } return } // AddKnowledgeClassify // @Description: 添加报告分类 // @author: Roc // @datetime 2024-06-17 11:01:21 // @param classifyName string // @param parentId int // @param chartPermissionIdList []int // @return err error // @return errMsg string // @return isSendEmail bool func AddKnowledgeClassify(classifyName string, parentId, resourceType int) (err error, errMsg string, isSendEmail bool) { isSendEmail = true errMsg = `添加失败` knowledgeObj := new(knowledge.KnowledgeClassify) _, err = knowledgeObj.GetClassifyByName(classifyName, parentId, resourceType) if err != nil && !utils.IsErrNoRow(err) { errMsg = "获取分类信息失败" return } if err == nil { errMsg = "分类名称:" + classifyName + "已存在" isSendEmail = false err = errors.New(errMsg) return } else { err = nil } level := 1 // 父级分类 var parentClassifyItem *knowledge.KnowledgeClassify // 父级分类下的子分类数量 var childClassifyCount int if parentId > 0 { // 获取父级分类信息 parentClassifyItem, err = knowledgeObj.GetClassifyById(parentId) if err != nil { errMsg = "获取父级分类信息失败" if utils.IsErrNoRow(err) { errMsg = "父级分类不存在" } return } if parentClassifyItem.ResourceType != resourceType { errMsg = "父级分类与当前分类类型不一致" err = fmt.Errorf(errMsg) return } level = parentClassifyItem.Level + 1 if level > 3 { errMsg = "分类层级不可超过三级" isSendEmail = false return } // 获取父级分类下的子分类数量 childClassifyCount, err = knowledgeObj.GetCountClassifyChildByParentId(parentId) if err != nil { errMsg = "获取父级分类的子分类信息失败" return } } nowTime := time.Now().Local() classify := new(knowledge.KnowledgeClassify) maxSort, err := classify.GetMaxSort() if err != nil { errMsg = "操作失败" err = errors.New("查询品种排序失败, Err: " + err.Error()) return } classify.ClassifyName = classifyName classify.ParentId = parentId classify.CreateTime = nowTime classify.ModifyTime = nowTime classify.Sort = maxSort + 1 classify.Enabled = 1 classify.Level = level classify.ResourceType = resourceType err = knowledgeObj.Add(classify) if err != nil { return } fmt.Println("classify.ClassifyId:") fmt.Println(classify.ClassifyId) // 如果父级分类不为空的话,那么就标记有子级分类,同时 if parentClassifyItem != nil { /*parentClassifyItem.HasChild = 1 err = parentClassifyItem.Update([]string{"HasChild"}) if err != nil { return } */ // 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系) if childClassifyCount <= 0 { moveResourceByAddClassify(parentClassifyItem, classify, resourceType) } } return } // 关于研报分类,因只允许报告或品种关联在最小分类下,所以当某个父分类(非三级分类)已关联报告或品种,需要在该父分类下增加子分类,则第一个子分类添加成功时,默认把该父分类关联的品种和报告转移至新创建的子分类(第一个子分类)下 // moveReportByAddClassify // @Description: 报告和章节的转移 // @author: Roc // @datetime 2024-06-17 16:29:56 // @param parentClassifyInfo *knowledge.KnowledgeClassify // @param currClassifyInfo *knowledge.KnowledgeClassify // @return err error func moveResourceByAddClassify(parentClassifyInfo, currClassifyInfo *knowledge.KnowledgeClassify, resourceType int) (err error) { defer func() { if err != nil { msg := fmt.Sprint("历史事件更改分类失败,父级分类ID:", parentClassifyInfo.ClassifyId, ";当前分类ID:", currClassifyInfo.ClassifyId, ";错误信息:", err.Error()) utils.FileLog.Error(msg) go alarm_msg.SendAlarmMsg(msg, 3) } }() if currClassifyInfo.Level > 3 { err = errors.New("父级分类不支持三级分类以上") return } // 报告的分类归属调整,转为下一级的分类 var condition string pars := make([]interface{}, 0) condition += ` AND resource_type = ? ` pars = append(pars, resourceType) // 查询是需要转移的资源数量 condition += ` AND classify_id = ? ` pars = append(pars, parentClassifyInfo.ClassifyId) idList, err := knowledge.GetKnowledgeResourceIdList(condition, pars) if err != nil { err = fmt.Errorf("查询需要转移的资源数量失败,Err: %s", err.Error()) return } if len(idList) == 0 { //没有需要转移的资源 return } newClassifyId := currClassifyInfo.ClassifyId if currClassifyInfo.Level == 2 { //查询排名第一的子分类 classifyObj := new(knowledge.KnowledgeClassify) childClassify, e := classifyObj.GetFirstClassifyByParentId(currClassifyInfo.ClassifyId) if e == nil { newClassifyId = childClassify.ClassifyId } } resourceObj := new(knowledge.KnowledgeResource) // 批量事件的分类ID err = resourceObj.UpdateClassifyIdByIds(idList, newClassifyId, resourceType) return } func EditKnowledgeClassify(classifyId, parentId int, classifyName string, resourceType int) (err error, errMsg string, isSendEmail bool) { isSendEmail = true errMsg = `修改失败` knowledgeObj := new(knowledge.KnowledgeClassify) item, err := knowledgeObj.GetClassifyById(classifyId) if err != nil { errMsg = "获取分类信息失败" if utils.IsErrNoRow(err) { errMsg = "分类不存在, 或已被删除" isSendEmail = false } return } if item.ResourceType != resourceType { errMsg = "分类类型错误" err = errors.New("分类类型错误") return } if (parentId == 0 && item.ParentId > 0) || (parentId > 0 && item.ParentId == 0) { err = errors.New("不允许修改分类层级") errMsg = "不允许修改分类层级" return } // 父级分类 var parentClassifyItem *knowledge.KnowledgeClassify // 父级分类下的子分类数量 var childClassifyCount int if parentId > 0 { // 获取父级分类信息 parentClassifyItem, err = knowledgeObj.GetClassifyById(parentId) if err != nil { errMsg = "获取父级分类信息失败" if utils.IsErrNoRow(err) { errMsg = "父级分类不存在" } return } if parentClassifyItem.ResourceType != resourceType { errMsg = "父级分类与当前分类类型不一致" err = fmt.Errorf(errMsg) return } if parentClassifyItem.Level+1 != item.Level { errMsg = "不允许修改分类层级" err = errors.New("不允许修改分类层级") return } level := parentClassifyItem.Level + 1 if level > 3 { errMsg = "分类层级不可超过三级" isSendEmail = false return } // 获取父级分类下的子分类数量 childClassifyCount, err = knowledgeObj.GetCountClassifyChildByParentId(parentId) if err != nil { errMsg = "获取父级分类的子分类信息失败" return } } //originName := item.ClassifyName // 重名校验 existName, e := knowledgeObj.GetClassifyByName(classifyName, parentId, item.ResourceType) if e != nil && !utils.IsErrNoRow(e) { errMsg = "分类名称已存在" err = errors.New("获取重名分类失败, Err: " + e.Error()) return } if existName != nil && existName.ClassifyId > 0 && existName.ClassifyId != item.ClassifyId { errMsg = "分类名称:" + classifyName + "已存在" err = errors.New(errMsg) isSendEmail = false return } item.ClassifyName = classifyName item.ParentId = parentId item.ModifyTime = time.Now().Local() cols := make([]string, 0) cols = append(cols, "ParentId", "ClassifyName", "ModifyTime") err = item.Update(cols) if err != nil { return } // 修改父级分类下相关的事件,找到当前分类的最小分类,把上一级的报告挪到最小分类上 // 如果父级分类不为空的话,那么就标记有子级分类,同时 if parentClassifyItem != nil { /*parentClassifyItem.HasChild = 1 err = parentClassifyItem.Update([]string{"HasChild"}) if err != nil { return }*/ // 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系) if childClassifyCount <= 0 { moveResourceByAddClassify(parentClassifyItem, item, resourceType) } } return } // GetClassifyTreeRecursive 递归获取分类树形结构 func GetClassifyTreeRecursive(list []*knowledge.KnowledgeClassifyItem, parentId int) []*knowledge.KnowledgeClassifyItem { res := make([]*knowledge.KnowledgeClassifyItem, 0) for _, v := range list { if v.ParentId == parentId { v.Child = GetClassifyTreeRecursive(list, v.ClassifyId) res = append(res, v) } } return res } // GetParentClassifyListByParentIdList // @Description: 递归获取父级分类信息,正常来讲只有三次 // @author: Roc // @datetime 2024-06-19 13:23:33 // @param parentClassifyIdList []int // @return list []*knowledge.KnowledgeClassifyItem // @return err error func GetParentClassifyListByParentIdList(parentClassifyIdList []int) (list []*knowledge.KnowledgeClassifyItem, err error) { knowledgeObj := new(knowledge.KnowledgeClassify) num := len(parentClassifyIdList) if num <= 0 { return } list, err = knowledgeObj.GetClassifyListByParentIdList(parentClassifyIdList) if err != nil { return } // 是否还有上级 { currParentClassifyIdList := make([]int, 0) for _, v := range list { if v.ParentId > 0 { currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId) } } if len(currParentClassifyIdList) > 0 { tmpList, tmpErr := GetParentClassifyListByParentIdList(currParentClassifyIdList) if tmpErr != nil { err = tmpErr return } list = append(tmpList, list...) } } return } // GetClassifyListTreeRecursive // @Description: 递归获取分类树形结构 // @author: Roc // @datetime 2024-06-19 13:23:28 // @param list []*knowledge.KnowledgeClassifyItem // @param parentId int // @return []*knowledge.KnowledgeClassifyItem func GetClassifyListTreeRecursive(list []*knowledge.KnowledgeClassifyItem, parentId int) []*knowledge.KnowledgeClassifyItem { res := make([]*knowledge.KnowledgeClassifyItem, 0) for _, v := range list { if v.ParentId == parentId { v.Child = GetClassifyListTreeRecursive(list, v.ClassifyId) res = append(res, v) } } // 前端的JP需要我这么返回 if len(res) <= 0 { res = nil } return res } // BySortAndCreateTime 用来排序,先按Sort字段升序排序,若Sort相同,则按照CreateTime字段升序排序。 type BySortAndCreateTime []*knowledge.KnowledgeClassifyItem func (a BySortAndCreateTime) Len() int { return len(a) } func (a BySortAndCreateTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a BySortAndCreateTime) Less(i, j int) bool { if a[i].Sort == a[j].Sort { return a[i].CreateTime.Before(a[j].CreateTime) } return a[i].Sort < a[j].Sort } // SortClassifyListBySortAndCreateTime sorts the ClassifyList slice by Sort and then CreateTime in ascending order. func SortClassifyListBySortAndCreateTime(classifyList []*knowledge.KnowledgeClassifyItem) { sort.Sort(BySortAndCreateTime(classifyList)) }