package services import ( "eta_gn/eta_report/models" "eta_gn/eta_report/utils" "fmt" "strconv" "strings" "sync" "time" ) // GetReportClassifyTreeRecursive 递归获取目录树 func GetReportClassifyTreeRecursive(list []*models.Classify, parentId int) []*models.ClassifyTreeItem { res := make([]*models.ClassifyTreeItem, 0) for _, v := range list { if v.ParentId == parentId { t := new(models.ClassifyTreeItem) t.ClassifyId = v.Id t.ClassifyName = v.ClassifyName t.ParentId = v.ParentId t.Sort = v.Sort t.Level = v.Level t.ClassifyType = v.ClassifyType t.HasChild = v.HasChild t.Children = GetReportClassifyTreeRecursive(list, v.Id) res = append(res, t) } } return res } func RecursiveFilterNoChildTreeClassify(list []*models.ClassifyTreeItem) []*models.ClassifyTreeItem { res := make([]*models.ClassifyTreeItem, 0) for _, v := range list { v.Children = RecursiveFilterNoChildTreeClassify(v.Children) if len(v.Children) == 0 && v.HasChild == 1 { continue } res = append(res, v) } return res } // GetReportByOutReportId 根据外部ID获取报告 func GetReportByOutReportId(outReportId int) (reportItem *models.Report, pptItem *models.PptV2) { reportOb := new(models.Report) cond := ` AND out_report_id = ?` pars := make([]interface{}, 0) pars = append(pars, outReportId) reportExist, _ := reportOb.GetItemByCondition(cond, pars, "") if reportExist != nil && reportExist.Id > 0 { reportItem = reportExist } pptOb := new(models.PptV2) pptExist, _ := pptOb.GetItemByCondition(cond, pars, "") if pptExist != nil && pptExist.PptId > 0 { pptItem = pptExist } return } // CreatePptReport 创建PPT报告 func CreatePptReport(outReportId, classifyId int, title string, topicEndTime time.Time, creator string, authors []string) (reportId int, err error) { defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("创建外部PPT报告失败, OutReportId: %d, %v", outReportId, err)) } }() // 获取用户 outIdAdmin := make(map[string]*models.Admin) { ob := new(models.Admin) list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取用户列表失败, %v", e) return } for _, v := range list { if v.OutId == "" { continue } outIdAdmin[v.OutId] = v } } creatorAdmin := outIdAdmin[creator] if creatorAdmin == nil { err = fmt.Errorf("创建人不存在, OutId: %s", creator) return } // 新建PPT基础信息 newItem := new(models.PptV2) newItem.Title = title newItem.AddType = utils.ReportAddTypeInherit newItem.ClassifyId = classifyId newItem.CollaborateType = utils.ReportWriteTypeGroup if len(authors) > 0 { var partnerArr []string for _, v := range authors { ad := outIdAdmin[v] // 忽略无法识别的工号 if ad == nil { continue } partnerArr = append(partnerArr, strconv.Itoa(ad.AdminId)) } newItem.CollaborateUsers = strings.Trim(strings.Join(partnerArr, ","), `"`) } newItem.PptVersion = 2 newItem.AdminId = creatorAdmin.AdminId newItem.AdminRealName = creatorAdmin.RealName newItem.ReportSource = utils.ReportSourceOuter // 固定外部PPT newItem.State = models.ReportStateWaitSubmit // 默认待提交 newItem.CreateTime = time.Now() newItem.ModifyTime = time.Now() newItem.OutReportId = strconv.Itoa(outReportId) newItem.TopicEndTime = topicEndTime newItem.TemplateType = 1 // 模板类型默认1,有继承那么就继承 // 自动继承该分类上一篇外部报告(审批通过的) inheritItem := new(models.PptV2) { ob := new(models.PptV2) cond := ` AND report_source = ? AND classify_id = ? AND state = ?` pars := make([]interface{}, 0) pars = append(pars, utils.ReportSourceOuter, classifyId, models.ReportStatePass) inheritItem, _ = ob.GetItemByCondition(cond, pars, "create_time DESC") } if inheritItem != nil && inheritItem.PptId > 0 { newItem.TemplateType = inheritItem.TemplateType newItem.BackgroundImg = inheritItem.BackgroundImg newItem.ReportType = inheritItem.ReportType newItem.PptDate = inheritItem.PptDate newItem.Content = inheritItem.Content newItem.CoverContent = inheritItem.CoverContent newItem.TitleSetting = inheritItem.TitleSetting } if e := newItem.Create(); e != nil { err = fmt.Errorf("新增PPT报告失败, %v", e) return } reportId = newItem.PptId //reportCode = utils.MD5(fmt.Sprintf("PPT%d", newItem.PptId)) // 更新报告分类计数 go func() { _ = UpdateClassifyReportNum(classifyId) }() return } // 更新分类报告计数加个锁 var classifyReportNumLock sync.Mutex // UpdateClassifyReportNum 更新分类报告计数 func UpdateClassifyReportNum(classifyId int) (err error) { classifyReportNumLock.Lock() defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("更新分类报告计数失败, %v", err)) } classifyReportNumLock.Unlock() }() classifyItem, e := models.GetClassifyById(classifyId) if e != nil { err = fmt.Errorf("获取分类失败, %v", e) return } // 更新分类报告数 var total int { reportOb := new(models.Report) var cond string switch classifyItem.Level { case 1: cond += ` AND classify_id_first = ?` case 2: cond += ` AND classify_id_second = ?` case 3: cond += ` AND classify_id_third = ?` } pars := make([]interface{}, 0) pars = append(pars, classifyId) count, e := reportOb.GetCountByCondition(cond, pars) if e != nil { err = fmt.Errorf("获取报告计数失败, %v", e) return } total += count } { pptOb := new(models.PptV2) cond := ` AND classify_id = ?` pars := make([]interface{}, 0) pars = append(pars, classifyId) count, e := pptOb.GetCountByCondition(cond, pars) if e != nil { err = fmt.Errorf("获取PPT报告计数失败, %v", e) return } total += count } classifyItem.ReportNum = total if e = classifyItem.UpdateClassify([]string{"ReportNum"}); e != nil { err = fmt.Errorf("更新分类报告计数失败, %v", e) return } // 获取所有分类, 更新父级, 无父级忽略 if classifyItem.ParentId <= 0 { return } classifyOb := new(models.Classify) classifies, e := classifyOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取报告列表失败, %v", e) return } classifyIdMap := make(map[int]*models.Classify) classifyParentChildMap := make(map[int][]*models.Classify) for _, v := range classifies { classifyIdMap[v.Id] = v if v.ParentId <= 0 { continue } if classifyParentChildMap[v.ParentId] == nil { classifyParentChildMap[v.ParentId] = make([]*models.Classify, 0) } classifyParentChildMap[v.ParentId] = append(classifyParentChildMap[v.ParentId], v) } // 递归获取需要更新的父级报告数 updateClassifies := CountParentClassifyReportNumRecursive(classifies, classifyItem.ParentId, classifyIdMap, classifyParentChildMap) if len(updateClassifies) == 0 { return } for _, v := range updateClassifies { if e = v.UpdateClassify([]string{"ReportNum"}); e != nil { err = fmt.Errorf("更新父级分类报告计数失败, %v", e) return } } return } // CountParentClassifyReportNumRecursive 递归统计父级分类报告数 func CountParentClassifyReportNumRecursive(list []*models.Classify, parentId int, classifyIdMap map[int]*models.Classify, classifyParentChildMap map[int][]*models.Classify) []*models.Classify { res := make([]*models.Classify, 0) for _, v := range list { // 找父级 if v.Id != parentId { continue } parentItem := classifyIdMap[v.Id] if parentItem == nil { break } // 合计所有直系子分类报告数 children := classifyParentChildMap[v.Id] if len(children) == 0 { break } var t int for _, child := range children { t += child.ReportNum } parentItem.ReportNum = t res = append(res, parentItem) // 继续向上统计父级 if v.ParentId <= 0 { break } parents := CountParentClassifyReportNumRecursive(list, v.ParentId, classifyIdMap, classifyParentChildMap) if len(parents) == 0 { break } res = append(res, parents...) } return res } // CreateReport 创建报告 func CreateReport(outReportId, classifyId int, title string, topicEndTime time.Time, creator string, authors []string) (reportId int, err error) { defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("创建外部报告失败, OutReportId: %d, %v", outReportId, err)) } }() // 获取用户 outIdAdmin := make(map[string]*models.Admin) { ob := new(models.Admin) list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取用户列表失败, %v", e) return } for _, v := range list { if v.OutId == "" { continue } outIdAdmin[v.OutId] = v } } creatorAdmin := outIdAdmin[creator] if creatorAdmin == nil { err = fmt.Errorf("创建人不存在, OutId: %s", creator) return } // 各级分类信息 var classifyIdFirst, classifyIdSecond, classifyIdThird int var classifyNameFirst, classifyNameSecond, classifyNameThird, classifyName string { classifyOb := new(models.Classify) classifies, e := classifyOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取报告列表失败, %v", e) return } classifyIdMap := make(map[int]*models.Classify) for _, v := range classifies { classifyIdMap[v.Id] = v } thisClassify := classifyIdMap[classifyId] if thisClassify == nil { err = fmt.Errorf("分类不存在, ID: %d", classifyId) return } classifyName = thisClassify.ClassifyName // 根据levelPath确认各级分类信息 levelArr := strings.Split(thisClassify.LevelPath, ",") levelLen := len(levelArr) if levelLen <= 0 { err = fmt.Errorf("分类层级信息有误, ID: %d, LevelPath: %s", classifyId, thisClassify.LevelPath) return } if levelLen > 2 { strThird := levelArr[2] classifyIdThird, _ = strconv.Atoi(strThird) classifyThird := classifyIdMap[classifyIdThird] if classifyThird != nil { classifyNameThird = classifyThird.ClassifyName } } if levelLen > 1 { strSecond := levelArr[1] classifyIdSecond, _ = strconv.Atoi(strSecond) classifySecond := classifyIdMap[classifyIdSecond] if classifySecond != nil { classifyNameSecond = classifySecond.ClassifyName } } if levelLen > 0 { strFirst := levelArr[0] classifyIdFirst, _ = strconv.Atoi(strFirst) classifyFirst := classifyIdMap[classifyIdFirst] if classifyFirst != nil { classifyNameFirst = classifyFirst.ClassifyName } } } // 新报告信息 newItem := new(models.Report) newItem.AddType = utils.ReportAddTypeInherit // 固定继承 newItem.ReportVersion = 2 // 固定新版报告 newItem.ClassifyIdFirst = classifyIdFirst newItem.ClassifyNameFirst = classifyNameFirst newItem.ClassifyIdSecond = classifyIdSecond newItem.ClassifyNameSecond = classifyNameSecond newItem.ClassifyIdThird = classifyIdThird newItem.ClassifyNameThird = classifyNameThird newItem.Title = title newItem.Frequency = "日度" // 默认日度吧,这个也没啥用 newItem.State = models.ReportStateWaitSubmit // 固定待提交 newItem.Stage = 0 // 期数去掉了 newItem.NeedSplice = 1 // TODO:是否默认拼接版头 newItem.CollaborateType = 2 // 固定协作报告 newItem.HasChapter = 1 // 协作报告固定有章节 newItem.ReportLayout = 2 // 固定智能布局 newItem.IsPublicPublish = 1 // 固定公开发布 newItem.ReportCreateTime = time.Now() newItem.ReportSource = utils.ReportSourceOuter // 固定外部报告 newItem.OutReportId = strconv.Itoa(outReportId) newItem.TopicEndTime = topicEndTime // 课题结束时间 newItem.AdminId = creatorAdmin.AdminId newItem.AdminRealName = creatorAdmin.RealName newItem.ContentModifyTime = time.Now() newItem.CreateTime = time.Now() newItem.ModifyTime = time.Now() newItem.LastModifyAdminId = creatorAdmin.AdminId newItem.LastModifyAdminName = creatorAdmin.RealName // 协作人信息 newGrants := make([]*models.ReportGrant, 0) var partnerIds []int if len(authors) > 0 { for _, v := range authors { ad := outIdAdmin[v] // 忽略无法识别的工号 if ad == nil { continue } partnerIds = append(partnerIds, ad.AdminId) } } for _, v := range partnerIds { newGrants = append(newGrants, &models.ReportGrant{ AdminId: v, CreateTime: time.Now(), }) } // 自动继承该分类上一篇外部报告(审批通过的) newChapters := make([]*models.ReportChapter, 0) chapterGrantsMapping := make(map[int][]int) inheritItem := new(models.Report) { ob := new(models.Report) cond := ` AND report_source = ? AND state = ? AND classify_id_first = ? AND classify_id_second = ? AND classify_id_third = ?` pars := make([]interface{}, 0) pars = append(pars, utils.ReportSourceOuter, models.ReportStatePass, classifyIdFirst, classifyIdSecond, classifyIdThird) inheritItem, _ = ob.GetItemByCondition(cond, pars, "create_time DESC") } if inheritItem != nil && inheritItem.Id > 0 { newItem.InheritReportId = inheritItem.Id newItem.Abstract = inheritItem.Abstract newItem.Content = inheritItem.Content newItem.ContentSub = inheritItem.ContentSub newItem.ContentStruct = inheritItem.ContentStruct newItem.HeadImg = inheritItem.HeadImg newItem.EndImg = inheritItem.EndImg newItem.CanvasColor = inheritItem.CanvasColor newItem.HeadResourceId = inheritItem.HeadResourceId newItem.EndResourceId = inheritItem.EndResourceId // 继承报告章节内容 chapterOb := new(models.ReportChapter) chapterCond := ` AND report_id = ?` chapterPars := make([]interface{}, 0) chapterPars = append(chapterPars, inheritItem.Id) inheritChapters, e := chapterOb.GetItemsByCondition(chapterCond, chapterPars, []string{}, "") if e != nil { err = fmt.Errorf("获取继承报告章节失败, %v", e) return } if len(inheritChapters) > 0 { var originChapterIds []int for _, v := range inheritChapters { originChapterIds = append(originChapterIds, v.ReportChapterId) //v.ReportChapterId = 0 // 此处不置空,插入时需要做新ID和旧ID的匹配 v.ReportId = 0 v.ClassifyIdFirst = classifyIdFirst v.ClassifyNameFirst = classifyNameFirst v.PublishState = 1 // 未发布 v.CreateTime = time.Now() v.ModifyTime = time.Now() v.ContentModifyTime = time.Now() v.LastModifyAdminId = creatorAdmin.AdminId v.LastModifyAdminName = creatorAdmin.RealName newChapters = append(newChapters, v) } // 这里需要继承原章节的授权,保留在报告协作人中依旧存在的,移除不在报告协作人中的 chapterGrantsOb := new(models.ReportChapterGrant) chapterGrantsCond := ` AND report_chapter_id IN (?)` chapterGrantsPars := make([]interface{}, 0) chapterGrantsPars = append(chapterGrantsPars, originChapterIds) originChapterGrants, e := chapterGrantsOb.GetItemsByCondition(chapterGrantsCond, chapterGrantsPars, []string{}, "") if e != nil { err = fmt.Errorf("获取继承章节授权失败, %v", e) return } for _, v := range originChapterGrants { if utils.InArrayByInt(partnerIds, v.AdminId) { chapterGrantsMapping[v.ReportChapterId] = append(chapterGrantsMapping[v.ReportChapterId], v.AdminId) } } } } else { // 找不到继承报告,则找下分类是否有对应的章节设置 typesOb := new(models.ReportChapterType) typesCond := ` AND report_classify_id = ?` typesPars := make([]interface{}, 0) typesPars = append(typesPars, classifyId) chapterTypes, e := typesOb.GetItemsByCondition(typesCond, typesPars, []string{}, "") if e != nil { err = fmt.Errorf("获取报告分类章节设置失败, %v", e) return } // 新增默认章节 for _, v := range chapterTypes { cp := new(models.ReportChapter) cp.AddType = 1 cp.Title = v.ReportChapterTypeName cp.ReportType = v.ResearchType cp.ClassifyIdFirst = classifyId cp.ClassifyNameFirst = classifyName cp.TypeId = v.ReportChapterTypeId cp.TypeName = v.ReportChapterTypeName cp.PublishState = 1 cp.Sort = v.Sort cp.CreateTime = newItem.CreateTime cp.ModifyTime = time.Now() cp.LastModifyAdminId = newItem.LastModifyAdminId cp.LastModifyAdminName = newItem.LastModifyAdminName cp.ContentModifyTime = time.Now() cp.ReportLayout = newItem.ReportLayout cp.ReportCreateTime = time.Now() newChapters = append(newChapters, cp) } } // 新增报告、章节以及协作人权限 newId, e := newItem.CreateReportAndChapters(newItem, newChapters, newGrants, chapterGrantsMapping) if e != nil { err = fmt.Errorf("新增报告、章节及授权失败, %v", e) return } if newId <= 0 { err = fmt.Errorf("新增报告ID为0") return } reportId = newId // 更新唯一编码、更新报告分类计数 go func() { newItem.ReportCode = utils.MD5(strconv.Itoa(newItem.Id)) if e = newItem.Update([]string{"ReportCode"}); e != nil { utils.FileLog.Info(fmt.Sprintf("报告唯一编码更想失败, ID: %d", newItem.Id)) } _ = UpdateClassifyReportNum(classifyId) }() return } // EditReport 编辑报告 func EditReport(reportItem *models.Report, title string, topicEndTime time.Time, authors []string) (err error) { if reportItem == nil { err = fmt.Errorf("报告信息有误") return } defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("编辑外部报告失败, OutReportId: %s, %v", reportItem.OutReportId, err)) } }() // 获取用户 outIdAdmin := make(map[string]*models.Admin) { ob := new(models.Admin) list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取用户列表失败, %v", e) return } for _, v := range list { if v.OutId == "" { continue } outIdAdmin[v.OutId] = v } } // 比对协作人,移除被删除协作人的权限 var removePartner []int { var originPartner []int var partnerIds []int if len(authors) > 0 { for _, v := range authors { ad := outIdAdmin[v] // 忽略无法识别的工号 if ad == nil { continue } partnerIds = append(partnerIds, ad.AdminId) } } grantOb := new(models.ReportGrant) grantCond := ` AND report_id = ?` grantPars := make([]interface{}, 0) grantPars = append(grantPars, reportItem.Id) grants, e := grantOb.GetItemsByCondition(grantCond, grantPars, []string{}, "") if e != nil { err = fmt.Errorf("获取报告授权失败, %v", e) return } for _, v := range grants { originPartner = append(originPartner, v.AdminId) } if len(partnerIds) == 0 { removePartner = originPartner } // 原协作人不在新协作人中则移除 for _, v := range originPartner { if !utils.InArrayByInt(partnerIds, v) { removePartner = append(removePartner, v) } } } // 获取章节IDs,已有章节清除授权 var chapterIds []int if len(removePartner) > 0 { chapterOb := new(models.ReportChapter) chapterCond := ` AND report_id = ?` chapterPars := make([]interface{}, 0) chapterPars = append(chapterPars, reportItem.Id) chapters, e := chapterOb.GetItemsByCondition(chapterCond, chapterPars, []string{"report_chapter_id"}, "") if e != nil { err = fmt.Errorf("获取报告章节失败, %v", e) return } for _, v := range chapters { chapterIds = append(chapterIds, v.ReportChapterId) } } // 更新报告和移除授权 reportItem.Title = title reportItem.TopicEndTime = topicEndTime reportItem.ModifyTime = time.Now() updateCols := []string{"Title", "TopicEndTime", "ModifyTime"} if e := reportItem.EditReportAndClearGrant(reportItem, updateCols, chapterIds, removePartner); e != nil { err = fmt.Errorf("更新报告失败, %v", e) return } return } // EditPptReport 编辑PPT报告 func EditPptReport(pptItem *models.PptV2, title string, topicEndTime time.Time, authors []string) (err error) { if pptItem == nil { err = fmt.Errorf("PPT报告信息有误") return } defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("编辑外部PPT报告失败, OutReportId: %s, %v", pptItem.OutReportId, err)) } }() // 获取用户 outIdAdmin := make(map[string]*models.Admin) { ob := new(models.Admin) list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "") if e != nil { err = fmt.Errorf("获取用户列表失败, %v", e) return } for _, v := range list { if v.OutId == "" { continue } outIdAdmin[v.OutId] = v } } // 新建PPT基础信息 pptItem.Title = title pptItem.TopicEndTime = topicEndTime if len(authors) > 0 { var partnerArr []string for _, v := range authors { ad := outIdAdmin[v] // 忽略无法识别的工号 if ad == nil { continue } partnerArr = append(partnerArr, strconv.Itoa(ad.AdminId)) } pptItem.CollaborateUsers = strings.Trim(strings.Join(partnerArr, ","), `"`) } updateCols := []string{"Title", "TopicEndTime", "CollaborateUsers"} if e := pptItem.Update(updateCols); e != nil { err = fmt.Errorf("更新PPT报告失败, %v", e) return } return }