Browse Source

fix:报告分类调整

Roc 8 months ago
parent
commit
61f2cabc62

+ 19 - 360
controllers/classify.go

@@ -7,7 +7,6 @@ import (
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"fmt"
-	"time"
 )
 
 // 分类
@@ -52,174 +51,18 @@ func (this *ClassifyController) Add() {
 		br.Msg = "分类名称不可为空"
 		return
 	}
-	/*if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
-		br.Msg = "展示类型不可为空"
-		return
-	}
-	if menuMap[system.MenuSpecialHandleClassifyChildMenu] && len(req.MenuList) > 0 && req.ParentId != 0 {
-		br.Msg = "非一级分类不可添加子目录"
-		return
-	}
-	if menuMap[system.MenuSpecialHandleClassifyReportImgs] && (req.ShowType == 1 || req.ShowType == 3) && req.YbRightBanner == "" && req.ParentId == 0 { //当一级报告分类为列表、品种时,增加“报告合集配图”的配置项
-		br.Msg = "报告合集配图不可为空"
-		return
-	}*/
 
-	item, err := models.GetClassifyByName(req.ClassifyName, req.ParentId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取分类信息失败"
-		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
-		return
-	}
-	if item != nil {
-		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
-		return
-	}
-
-	nowTime := time.Now().Local()
-	classify := new(models.Classify)
-
-	maxSort, e := classify.GetMaxSort()
-	if e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "查询品种排序失败, Err: " + e.Error()
-		return
-	}
-	classify.ClassifyName = req.ClassifyName
-	classify.ParentId = req.ParentId
-	classify.CreateTime = nowTime
-	classify.ModifyTime = nowTime
-	classify.Sort = maxSort + 1
-	classify.Enabled = 1
-	classify.ShowType = 1 //默认列表格式
-	classify.IsShow = 1
-	/*classify.Abstract = req.Abstract
-	classify.Descript = req.Descript
-	classify.Abstract = req.Abstract
-	classify.Descript = req.Descript
-	classify.ReportAuthor = req.ReportAuthor
-	classify.AuthorDescript = req.AuthorDescript
-	classify.ColumnImgUrl = req.ColumnImgUrl
-	classify.ReportImgUrl = req.ReportImgUrl
-	classify.HeadImgUrl = req.HeadImgUrl
-	classify.AvatarImgUrl = req.AvatarImgUrl
-	classify.HomeImgUrl = req.HomeImgUrl
-	classify.ClassifyLabel = req.ClassifyLabel
-	classify.ShowType = req.ShowType
-	classify.HasTeleconference = req.HasTeleconference
-	classify.VipTitle = req.VipTitle
-
-	classify.IsShow = req.IsShow
-	classify.YbFiccSort = req.YbFiccSort
-	classify.YbFiccIcon = req.YbFiccIcon
-	classify.YbFiccPcIcon = req.YbFiccPcIcon
-	classify.YbIconUrl = req.YbIconUrl
-	classify.YbBgUrl = req.YbBgUrl
-	classify.YbListImg = req.YbListImg
-	classify.YbShareBgImg = req.YbShareBgImg
-	classify.YbRightBanner = req.YbRightBanner
-	classify.RelateTel = req.RelateTel
-	classify.RelateVideo = req.RelateVideo
-	if req.ParentId > 0 {
-		parentClassify := new(models.Classify)
-		if parentClassify, err = models.GetClassifyById(req.ParentId); err != nil {
-			br.Msg = "获取父级分类信息失败"
-			br.ErrMsg = "获取父级分类信息失败, Err:" + err.Error()
-			return
-		}
-		updateParent := false
-		updateCols := make([]string, 0)
-		updateCols = append(updateCols, "HasTeleconference")
-		if req.HasTeleconference == 1 {
-			// 二级分类包含电话会,则一级分类也默认包含电话会
-			if parentClassify.HasTeleconference == 0 {
-				parentClassify.HasTeleconference = 1
-				updateParent = true
-			}
-		} else {
-			// 二级分类均无电话会,则一级分类也无电话会
-			if parentClassify.HasTeleconference == 1 {
-				child, err := models.GetClassifyChild(parentClassify.Id, "")
-				if err != nil {
-					br.Msg = "获取子分类失败"
-					br.ErrMsg = "获取子分类失败,Err:" + err.Error()
-					return
-				}
-				// 存在同一级分类下的二级分类有电话会则不变动
-				hasTel := false
-				for i := 0; i < len(child); i++ {
-					if child[i].HasTeleconference == 1 {
-						hasTel = true
-						break
-					}
-				}
-				if !hasTel {
-					parentClassify.HasTeleconference = 0
-					updateParent = true
-				}
-			}
-		}
-		if updateParent {
-			if err = parentClassify.UpdateClassify(updateCols); err != nil {
-				br.Msg = "更新父级分类失败"
-				br.ErrMsg = "更新父级分类失败, Err:" + err.Error()
-				return
-			}
-		}
-	}*/
-	err = models.AddClassify(classify)
+	// 新增分类
+	err, errMsg, isSentEmail := services.AddReportClassify(req.ClassifyName, req.ParentId, req.ChartPermissionIdList)
 	if err != nil {
-		br.Msg = "新增失败"
-		br.ErrMsg = "新增失败,Err:" + err.Error()
-		return
-	}
-
-	// 一级分类-新增子目录
-	/*if classify.ParentId == 0 && len(req.MenuList) > 0 {
-		menus := make([]*models.ClassifyMenu, 0)
-		for i := range req.MenuList {
-			menus = append(menus, &models.ClassifyMenu{
-				MenuName:   req.MenuList[i].MenuName,
-				ClassifyId: classify.Id,
-				Sort:       i + 1,
-				CreateTime: nowTime,
-				ModifyTime: nowTime,
-			})
-		}
-		menuObj := new(models.ClassifyMenu)
-		if e := menuObj.InsertMulti(menus); e != nil {
-			br.Msg = "新增子目录失败"
-			br.ErrMsg = "批量新增子目录失败, Err:" + e.Error()
-			return
+		br.Msg = "添加失败"
+		if errMsg != "" {
+			br.Msg = errMsg
 		}
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		br.IsSendEmail = isSentEmail
+		return
 	}
-	// 二级分类-新增子目录关联
-	if classify.ParentId > 0 && req.ClassifyMenuId > 0 {
-		if e := models.DeleteAndInsertClassifyMenuRelation(classify.Id, req.ClassifyMenuId); e != nil {
-			br.Msg = "新增子目录关联失败"
-			br.ErrMsg = "新增子目录关联失败, Err:" + e.Error()
-			return
-		}
-	}*/
-	//获取报告分类权限列表
-	if classify.ParentId > 0 { //二级分类才能修改权限
-		err = models.EditChartPermissionSearchKeyWordMappingMulti(req.ClassifyName, req.ChartPermissionIdList, classify.Id)
-		if err != nil {
-			br.Msg = "修改分类权限失败"
-			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
-			return
-		}
-		go func() {
-			_ = services.EditClassifyChartPermissionSync(req.ClassifyName, classify.Id)
-		}()
-	}
-
-	// 新增关联了电话会的二级分类时, 同步FICC活动分类
-	//if req.ParentId > 0 && req.RelateTel == 1 {
-	//	go func() {
-	//		_ = yb.SyncClassifyAndFiccActivityType()
-	//	}()
-	//}
 
 	br.Ret = 200
 	br.Success = true
@@ -360,6 +203,11 @@ func (this *ClassifyController) Delete() {
 		br.Msg = "参数错误"
 		return
 	}
+
+	br.Msg = "报告分类不允许删除"
+	br.IsSendEmail = false
+	return
+
 	item, err := models.GetClassifyById(req.ClassifyId)
 	if err != nil {
 		br.Msg = "获取信息失败"
@@ -407,20 +255,6 @@ func (this *ClassifyController) Edit() {
 		return
 	}
 
-	// 获取系统菜单, 如果没有对应的字段的特殊处理项, 则忽略必填
-	/*menus, e := system.GetSysMenuItemsByCondition(` AND hidden = 0`, make([]interface{}, 0), []string{}, ``)
-	if e != nil {
-		br.Msg = "保存失败"
-		br.ErrMsg = "获取菜单列表失败, Err: " + e.Error()
-		return
-	}
-	menuMap := make(map[string]bool)
-	for _, m := range menus {
-		if m.ButtonCode != "" {
-			menuMap[m.ButtonCode] = true
-		}
-	}*/
-
 	if req.ClassifyId <= 0 {
 		br.Msg = "参数错误"
 		return
@@ -429,193 +263,18 @@ func (this *ClassifyController) Edit() {
 		br.Msg = "分类名称不可为空"
 		return
 	}
-	/*if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
-		br.Msg = "展示类型不可为空"
-		return
-	}
-	if req.ParentId == req.ClassifyId {
-		br.Msg = "上级分类不能选择自己"
-		return
-	}
-	if menuMap[system.MenuSpecialHandleClassifyReportImgs] && (req.ShowType == 1 || req.ShowType == 3) && req.YbRightBanner == "" && req.ParentId == 0 { //当一级报告分类为列表、品种时,增加“报告合集配图”的配置项
-		br.Msg = "报告合集配图不可为空"
-		return
-	}*/
 
-	item, err := models.GetClassifyById(req.ClassifyId)
+	// 修改分类
+	err, errMsg, isSentEmail := services.EditReportClassify(req.ClassifyId, req.ClassifyName, req.ChartPermissionIdList)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
-			br.Msg = "分类不存在, 或已被删除"
-			br.ErrMsg = "获取分类信息失败, Err: " + err.Error()
-			return
-		}
-		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取信息失败,Err:" + err.Error()
-		return
-	}
-	originName := item.ClassifyName
-	oldParentId := item.ParentId
-	//originRelateTel := item.RelateTel
-
-	// 重名校验
-	existName, e := models.GetClassifyByName(req.ClassifyName, item.ParentId)
-	if e != nil && e.Error() != utils.ErrNoRow() {
-		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取重名分类失败, Err: " + err.Error()
-		return
-	}
-	if existName != nil && existName.Id != item.Id {
-		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
-		return
-	}
-	item.ClassifyName = req.ClassifyName
-	item.ParentId = req.ParentId
-	item.ModifyTime = time.Now().Local()
-	cols := make([]string, 0)
-	cols = append(cols, "ClassifyName", "ParentId", "ModifyTime")
-	if e := item.UpdateClassify(cols); e != nil {
 		br.Msg = "修改失败"
-		br.ErrMsg = "修改失败,Err:" + e.Error()
-		return
-	}
-
-	/*
-		item.Abstract = req.Abstract
-		item.Descript = req.Descript
-		item.ReportAuthor = req.ReportAuthor
-		item.AuthorDescript = req.AuthorDescript
-		item.ColumnImgUrl = req.ColumnImgUrl
-		item.HeadImgUrl = req.HeadImgUrl
-		item.AvatarImgUrl = req.AvatarImgUrl
-		item.ReportImgUrl = req.ReportImgUrl
-		item.HomeImgUrl = req.HomeImgUrl
-		item.ClassifyLabel = req.ClassifyLabel
-		item.ShowType = req.ShowType
-		item.HasTeleconference = req.HasTeleconference
-		item.VipTitle = req.VipTitle
-		//	item.Sort = req.Sort
-		item.IsShow = req.IsShow
-		item.YbFiccSort = req.YbFiccSort
-		item.YbFiccIcon = req.YbFiccIcon
-		item.YbFiccPcIcon = req.YbFiccPcIcon
-		item.YbIconUrl = req.YbIconUrl
-		item.YbBgUrl = req.YbBgUrl
-		item.YbListImg = req.YbListImg
-		item.YbShareBgImg = req.YbShareBgImg
-		item.YbRightBanner = req.YbRightBanner
-		item.RelateTel = req.RelateTel
-		item.RelateVideo = req.RelateVideo
-		item.ModifyTime = time.Now().Local()
-		cols := make([]string, 0)
-		cols = append(cols, "ClassifyName", "Abstract", "ParentId", "Descript", "ReportAuthor", "AuthorDescript", "ColumnImgUrl",
-			"HeadImgUrl", "AvatarImgUrl", "ReportImgUrl", "HomeImgUrl", "ClassifyLabel", "ShowType", "HasTeleconference", "VipTitle", "Sort",
-			"IsShow", "YbFiccSort", "YbFiccIcon", "YbFiccPcIcon", "YbIconUrl", "YbBgUrl", "YbListImg", "YbShareBgImg", "YbRightBanner",
-			"RelateTel", "RelateVideo", "ModifyTime")
-		if e := item.UpdateClassify(cols); e != nil {
-			br.Msg = "修改失败"
-			br.ErrMsg = "修改失败,Err:" + e.Error()
-			return
-		}
-		// 一级分类关联设置会强制修改二级分类的所有关联设置
-		if item.ParentId == 0 {
-			if e = models.UpdateChildClassifyRelateSetting(item.Id, req.RelateTel, req.RelateVideo); e != nil {
-				br.Msg = "更新二级分类关联设置失败"
-				br.ErrMsg = "更新二级分类关联设置失败, Err: " + e.Error()
-				return
-			}
-		}
-	*/
-	// 为二级分类时, 更新父级分类是否含电话会字段
-	if req.ParentId > 0 {
-		//二级分类才能修改权限
-		err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, req.ChartPermissionIdList, req.ClassifyId)
-		if err != nil {
-			br.Msg = "修改分类权限失败"
-			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
-			return
+		if errMsg != "" {
+			br.Msg = errMsg
 		}
-		go func() {
-			_ = services.EditClassifyChartPermissionSync(item.ClassifyName, req.ClassifyId)
-		}()
-		/*go func() {
-			_ = services.UpdateParentClassifyHasTel(req.ClassifyId, req.ParentId, req.HasTeleconference)
-		}()*/
-	}
-
-	// 更新报告分类名称/父级分类后
-	go func() {
-		_ = services.AfterUpdateClassifyNameOrParent(item.Id, item.ParentId, oldParentId, originName, item.ClassifyName)
-	}()
-
-	// 获取编辑前子目录列表
-	/*classifyId := item.Id
-	var menuCond string
-	var menuPars []interface{}
-	menuCond += ` AND classify_id = ?`
-	menuPars = append(menuPars, classifyId)
-	menuList, e := models.GetClassifyMenuList(menuCond, menuPars)
-	if e != nil {
-		br.Msg = "保存失败"
-		br.ErrMsg = "获取分类子目录列表失败, Err:" + e.Error()
+		br.ErrMsg = "修改失败,Err:" + err.Error()
+		br.IsSendEmail = isSentEmail
 		return
 	}
-	oriMenuIds := make([]int, 0)
-	for i := range menuList {
-		oriMenuIds = append(oriMenuIds, menuList[i].MenuId)
-	}
-
-	// 一级分类-新增/编辑/删除子目录
-	if item.ParentId == 0 && len(req.MenuList) > 0 {
-		nowTime := time.Now().Local()
-		insertMenus := make([]*models.ClassifyMenu, 0)
-		editMenus := make([]*models.ClassifyMenu, 0)
-		deleteMenuIds := make([]int, 0)
-		menuIds := make([]int, 0)
-		for i := range req.MenuList {
-			m := req.MenuList[i]
-
-			v := new(models.ClassifyMenu)
-			v.MenuName = req.MenuList[i].MenuName
-			v.ClassifyId = classifyId
-			v.Sort = i + 1
-			v.MenuId = m.MenuId
-			v.ModifyTime = nowTime
-			if v.MenuId > 0 {
-				// 编辑
-				editMenus = append(editMenus, v)
-				menuIds = append(menuIds, m.MenuId)
-			} else {
-				// 新增
-				v.CreateTime = nowTime
-				insertMenus = append(insertMenus, v)
-			}
-		}
-		// 编辑前存在子目录则取"编辑前子目录IDs与编辑时子目录IDs的差集"作为删除IDs
-		if len(oriMenuIds) > 0 {
-			deleteMenuIds = utils.MinusInt(oriMenuIds, menuIds)
-		}
-		if e = models.InsertAndUpdateClassifyMenu(insertMenus, editMenus, deleteMenuIds); e != nil {
-			br.Msg = "保存失败"
-			br.ErrMsg = "新增/编辑/删除分类子目录失败, Err:" + e.Error()
-			return
-		}
-	}
-
-	// 二级分类-新增子目录关联
-	if item.ParentId > 0 {
-		if e := models.DeleteAndInsertClassifyMenuRelation(classifyId, req.ClassifyMenuId); e != nil {
-			br.Msg = "新增子目录关联失败"
-			br.ErrMsg = "新增子目录关联失败, Err:" + e.Error()
-			return
-		}
-	}*/
-
-	// 关联电话会选项被更改时, 同步FICC活动分类
-	//if originRelateTel != req.RelateTel {
-	//	go func() {
-	//		_ = yb.SyncClassifyAndFiccActivityType()
-	//	}()
-	//}
 
 	br.Ret = 200
 	br.Success = true

+ 16 - 6
controllers/report_chapter.go

@@ -93,10 +93,24 @@ func (this *ReportController) AddChapter() {
 	//	req.Content = newContent
 	//}
 
+	// 最小单元的分类
+	var minClassifyId int
+	var minClassifyName string
+	if reportInfo.ClassifyIdThird > 0 {
+		minClassifyId = reportInfo.ClassifyIdThird
+		minClassifyName = reportInfo.ClassifyNameThird
+	} else if reportInfo.ClassifyIdSecond > 0 {
+		minClassifyId = reportInfo.ClassifyIdSecond
+		minClassifyName = reportInfo.ClassifyNameSecond
+	} else {
+		minClassifyId = reportInfo.ClassifyIdFirst
+		minClassifyName = reportInfo.ClassifyNameFirst
+	}
+
 	reportChapterInfo := new(models.ReportChapter)
 	reportChapterInfo.ReportId = reportInfo.Id
-	reportChapterInfo.ClassifyIdFirst = reportInfo.ClassifyIdFirst
-	reportChapterInfo.ClassifyNameFirst = reportInfo.ClassifyNameFirst
+	reportChapterInfo.ClassifyIdFirst = minClassifyId
+	reportChapterInfo.ClassifyNameFirst = minClassifyName
 
 	reportChapterInfo.Title = req.Title
 	reportChapterInfo.AddType = 1
@@ -109,10 +123,6 @@ func (this *ReportController) AddChapter() {
 	reportChapterInfo.CreateTime = reportInfo.CreateTime
 	reportChapterInfo.VideoKind = 2
 
-	reportChapterInfo.ClassifyIdSecond = reportInfo.ClassifyIdSecond
-	reportChapterInfo.ClassifyNameSecond = reportInfo.ClassifyNameSecond
-	reportChapterInfo.ClassifyIdThird = reportInfo.ClassifyIdThird
-	reportChapterInfo.ClassifyNameThird = reportInfo.ClassifyNameThird
 	reportChapterInfo.LastModifyAdminId = sysUser.AdminId
 	reportChapterInfo.LastModifyAdminName = sysUser.RealName
 	reportChapterInfo.ContentModifyTime = time.Now()

+ 9 - 0
controllers/report_chapter_type.go

@@ -280,6 +280,15 @@ func (this *ReportChapterTypeController) Edit() {
 		return
 	}
 	originName := item.ReportChapterTypeName
+	if item.ReportChapterTypeName != req.ReportChapterTypeName {
+		item.ReportChapterTypeName = req.ReportChapterTypeName
+		err := item.Update([]string{"ReportChapterTypeName"})
+		if err != nil {
+			br.Msg = "修改失败"
+			br.ErrMsg = "修改章节类型失败, Err: " + err.Error()
+			return
+		}
+	}
 	//更新章节权限
 	// todo 更新章节权限
 	cond = ` and product_id=1`

+ 17 - 0
models/classify.go

@@ -41,6 +41,8 @@ type Classify struct {
 	RelateVideo       int       `description:"是否在路演视频中可选: 0-否; 1-是"`
 	IsMassSend        int       `description:"1:群发,0:非群发"`
 	Enabled           int       `description:"是否可用,1可用,0禁用"`
+	Level             int       `description:"层级"`
+	HasChild          int       `description:"是否有子级别,0:下面没有子分类,1:下面有子分类;默认:0"`
 }
 
 type ClassifyAddReq struct {
@@ -488,3 +490,18 @@ func (classifyInfo *Classify) SetEnabled(id, enabled int) (err error) {
 	}
 	return
 }
+
+// GetCountClassifyChildByParentId
+// @Description: 获取父级分类下子分类数量
+// @author: Roc
+// @datetime 2024-06-17 10:58:46
+// @param parentId int
+// @return total int
+// @return err error
+func GetCountClassifyChildByParentId(parentId int) (total int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT count(1) AS total FROM classify WHERE parent_id = ? `
+	err = o.Raw(sql, parentId).QueryRow(&total)
+
+	return
+}

+ 0 - 4
models/report_chapter.go

@@ -36,10 +36,6 @@ type ReportChapter struct {
 	CreateTime          string    `description:"创建时间"`
 	ModifyTime          time.Time `description:"修改时间"`
 	OriginalVideoUrl    string    `description:"原始音频文件URL"`
-	ClassifyIdSecond    int       `description:"二级分类id"`
-	ClassifyNameSecond  string    `description:"二级分类名称"`
-	ClassifyIdThird     int       `description:"三级分类id"`
-	ClassifyNameThird   string    `description:"三级分类名称"`
 	ContentStruct       string    `description:"内容组件"`
 	LastModifyAdminId   int       `description:"最后更新人ID"`
 	LastModifyAdminName string    `description:"最后更新人姓名"`

+ 41 - 23
models/report_chapter_type.go

@@ -8,29 +8,30 @@ import (
 )
 
 type ReportChapterType struct {
-	ReportChapterTypeId    int       `orm:"column(report_chapter_type_id);pk" description:"报告章节类型id"`
-	ReportChapterTypeKey   string    `description:"章节key"`
-	ReportChapterTypeThumb string    `description:"H5展示的图片"`
-	BannerUrl              string    `description:"banner显示图片"`
-	ReportChapterTypeName  string    `description:"报告章节类型名称"`
-	Sort                   int       `description:"排序字段"`
-	Enabled                int       `description:"启禁用状态"`
-	CreatedTime            time.Time `description:"创建时间"`
-	LastUpdatedTime        time.Time `description:"更新时间"`
-	ResearchType           string    `description:"研报类型"`
-	SelectedImage          string    `description:"选中时的图片"`
-	UnselectedImage        string    `description:"没选中时的图片"`
-	PcSelectedImage        string    `description:"PC-选中的图片"`
-	PcUnselectedImage      string    `description:"PC-未选中的图片"`
-	EditImgUrl             string    `description:"管理后台编辑时选用的图"`
-	TickerTitle            string    `description:"指标列的标题"`
-	IsShow                 int       `description:"是否显示(研报小程序端根据此字段判断)"`
-	PauseStartTime         string    `description:"暂停开始日期"`
-	PauseEndTime           string    `description:"暂停结束日期"`
-	IsSet                  int       `description:"是否设置:0为设置,1已设置"`
-	YbIconUrl              string    `description:"研报小程序icon"`
-	YbBottomIcon           string    `description:"研报小程序详情底部icon"`
-	ReportClassifyId       int       `description:"所属分类id"`
+	ReportChapterTypeId        int       `orm:"column(report_chapter_type_id);pk" description:"报告章节类型id"`
+	ReportChapterTypeKey       string    `description:"章节key"`
+	ReportChapterTypeThumb     string    `description:"H5展示的图片"`
+	BannerUrl                  string    `description:"banner显示图片"`
+	ReportChapterTypeName      string    `description:"报告章节类型名称"`
+	Sort                       int       `description:"排序字段"`
+	Enabled                    int       `description:"启禁用状态"`
+	CreatedTime                time.Time `description:"创建时间"`
+	LastUpdatedTime            time.Time `description:"更新时间"`
+	ResearchType               string    `description:"研报类型"`
+	SelectedImage              string    `description:"选中时的图片"`
+	UnselectedImage            string    `description:"没选中时的图片"`
+	PcSelectedImage            string    `description:"PC-选中的图片"`
+	PcUnselectedImage          string    `description:"PC-未选中的图片"`
+	EditImgUrl                 string    `description:"管理后台编辑时选用的图"`
+	TickerTitle                string    `description:"指标列的标题"`
+	IsShow                     int       `description:"是否显示(研报小程序端根据此字段判断)"`
+	PauseStartTime             string    `description:"暂停开始日期"`
+	PauseEndTime               string    `description:"暂停结束日期"`
+	IsSet                      int       `description:"是否设置:0为设置,1已设置"`
+	YbIconUrl                  string    `description:"研报小程序icon"`
+	YbBottomIcon               string    `description:"研报小程序详情底部icon"`
+	ReportClassifyId           int       `description:"所属分类id"`
+	InheritReportChapterTypeId int       `description:"继承的报告章节类型id"`
 }
 
 func (r *ReportChapterType) Create() (err error) {
@@ -43,6 +44,23 @@ func (r *ReportChapterType) Create() (err error) {
 	return
 }
 
+// MultiCreate
+// @Description: 批量添加报告章节类型
+// @author: Roc
+// @receiver r
+// @datetime 2024-06-17 14:36:09
+// @param addList []*ReportChapterType
+// @return err error
+func (r *ReportChapterType) MultiCreate(addList []*ReportChapterType) (err error) {
+	if len(addList) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.InsertMulti(500, addList)
+
+	return
+}
+
 func (r *ReportChapterType) Update(cols []string) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	_, err = o.Update(r, cols...)

+ 63 - 0
models/report_v2.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"eta/eta_api/models/report"
 	"eta/eta_api/utils"
 	"github.com/beego/beego/v2/client/orm"
@@ -357,3 +358,65 @@ func GetReportListByAuthorized(condition string, pars []interface{}, startSize,
 	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
 	return
 }
+
+// ModifyReportClassifyAndReportChapterTypeByCondition
+// @Description:
+// @author: Roc
+// @datetime 2024-06-17 16:12:44
+// @param condition string
+// @param pars []interface{}
+// @param updateStr string
+// @param chapterTypeIdMap map[int]int 当前的章节类型ID ---> 继承的章节类型ID
+// @param oldClassifyId int
+// @param currClassifyId int
+// @param currClassifyName string
+// @return err error
+func ModifyReportClassifyAndReportChapterTypeByCondition(condition string, pars []interface{}, updateStr string, chapterTypeIdMap map[int]int, oldClassifyId, currClassifyId int, currClassifyName string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	if condition == `` {
+		err = errors.New("condition不能为空")
+		return
+	}
+	// 修改报告的所属分类
+	sql := `UPDATE report as a SET ` + updateStr + ` WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		return
+	}
+
+	// 修改历史报告中的章节分类归属
+	sql = `UPDATE report_chapter set classify_id_first=?,classify_name_first=? where classify_id_first = ?`
+	_, err = to.Raw(sql, currClassifyId, currClassifyName, oldClassifyId).Exec()
+	if err != nil {
+		return
+	}
+
+	for currTypeId, oldTypeId := range chapterTypeIdMap {
+		// 没有章节类型的不处理
+		if oldTypeId == 0 {
+			continue
+		}
+		tmpSql := `UPDATE report_chapter set type_id=? where type_id = ?`
+		_, err = to.Raw(tmpSql, currTypeId, oldTypeId).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 1 - 0
services/chart_permission_sync.go

@@ -102,6 +102,7 @@ type EditClassifyPermissionReq struct {
 
 // EditClassifyChartPermissionSync 设置报告分类权限
 func EditClassifyChartPermissionSync(keyword string, classifyId int) (err error) {
+	// TODO CRM的报告分类权限同步
 	defer func() {
 		if err != nil {
 			utils.FileLog.Info("同步设置报告分类权限失败, Err: " + err.Error())

+ 379 - 0
services/classify.go

@@ -1,6 +1,7 @@
 package services
 
 import (
+	"errors"
 	"eta/eta_api/models"
 	"eta/eta_api/utils"
 	"fmt"
@@ -177,3 +178,381 @@ func moveReportClassify(classifyInfo, prevClassify, nextClassify *models.Classif
 	}
 	return
 }
+
+// AddReportClassify
+// @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 AddReportClassify(classifyName string, parentId int, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+	errMsg = `添加失败`
+	item, err := models.GetClassifyByName(classifyName, parentId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		errMsg = "获取分类信息失败"
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类名称:" + classifyName + "已存在"
+			isSendEmail = false
+		}
+		return
+	}
+	if item != nil {
+		errMsg = "分类名称:" + classifyName + "已存在"
+		isSendEmail = false
+		err = errors.New(errMsg)
+		return
+	}
+
+	level := 1
+
+	// 父级分类
+	var parentClassifyItem *models.Classify
+	// 父级分类下的子分类数量
+	var childClassifyCount int
+
+	if parentId > 0 {
+		// 获取父级分类信息
+		parentClassifyItem, err = models.GetClassifyById(parentId)
+		if err != nil {
+			errMsg = "获取父级分类信息失败"
+			if err.Error() == utils.ErrNoRow() {
+				errMsg = "父级分类不存在"
+			}
+			return
+		}
+		level = parentClassifyItem.Level + 1
+
+		if level > 3 {
+			errMsg = "分类层级不可超过三级"
+			isSendEmail = false
+			return
+		}
+
+		// 获取父级分类下的子分类数量
+		childClassifyCount, err = models.GetCountClassifyChildByParentId(parentId)
+		if err != nil {
+			errMsg = "获取父级分类的子分类信息失败"
+			return
+		}
+
+	}
+
+	nowTime := time.Now().Local()
+	classify := new(models.Classify)
+
+	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.ShowType = 1 //默认列表格式
+	classify.IsShow = 1
+	classify.Level = level
+	/*classify.Abstract = req.Abstract
+	classify.Descript = req.Descript
+	classify.Abstract = req.Abstract
+	classify.Descript = req.Descript
+	classify.ReportAuthor = req.ReportAuthor
+	classify.AuthorDescript = req.AuthorDescript
+	classify.ColumnImgUrl = req.ColumnImgUrl
+	classify.ReportImgUrl = req.ReportImgUrl
+	classify.HeadImgUrl = req.HeadImgUrl
+	classify.AvatarImgUrl = req.AvatarImgUrl
+	classify.HomeImgUrl = req.HomeImgUrl
+	classify.ClassifyLabel = req.ClassifyLabel
+	classify.ShowType = req.ShowType
+	classify.HasTeleconference = req.HasTeleconference
+	classify.VipTitle = req.VipTitle
+
+	classify.IsShow = req.IsShow
+	classify.YbFiccSort = req.YbFiccSort
+	classify.YbFiccIcon = req.YbFiccIcon
+	classify.YbFiccPcIcon = req.YbFiccPcIcon
+	classify.YbIconUrl = req.YbIconUrl
+	classify.YbBgUrl = req.YbBgUrl
+	classify.YbListImg = req.YbListImg
+	classify.YbShareBgImg = req.YbShareBgImg
+	classify.YbRightBanner = req.YbRightBanner
+	classify.RelateTel = req.RelateTel
+	classify.RelateVideo = req.RelateVideo
+	if req.ParentId > 0 {
+		parentClassify := new(models.Classify)
+		if parentClassify, err = models.GetClassifyById(req.ParentId); err != nil {
+			br.Msg = "获取父级分类信息失败"
+			br.ErrMsg = "获取父级分类信息失败, Err:" + err.Error()
+			return
+		}
+		updateParent := false
+		updateCols := make([]string, 0)
+		updateCols = append(updateCols, "HasTeleconference")
+		if req.HasTeleconference == 1 {
+			// 二级分类包含电话会,则一级分类也默认包含电话会
+			if parentClassify.HasTeleconference == 0 {
+				parentClassify.HasTeleconference = 1
+				updateParent = true
+			}
+		} else {
+			// 二级分类均无电话会,则一级分类也无电话会
+			if parentClassify.HasTeleconference == 1 {
+				child, err := models.GetClassifyChild(parentClassify.Id, "")
+				if err != nil {
+					br.Msg = "获取子分类失败"
+					br.ErrMsg = "获取子分类失败,Err:" + err.Error()
+					return
+				}
+				// 存在同一级分类下的二级分类有电话会则不变动
+				hasTel := false
+				for i := 0; i < len(child); i++ {
+					if child[i].HasTeleconference == 1 {
+						hasTel = true
+						break
+					}
+				}
+				if !hasTel {
+					parentClassify.HasTeleconference = 0
+					updateParent = true
+				}
+			}
+		}
+		if updateParent {
+			if err = parentClassify.UpdateClassify(updateCols); err != nil {
+				br.Msg = "更新父级分类失败"
+				br.ErrMsg = "更新父级分类失败, Err:" + err.Error()
+				return
+			}
+		}
+	}*/
+	err = models.AddClassify(classify)
+	if err != nil {
+		return
+	}
+
+	//获取报告分类权限列表
+	err = models.EditChartPermissionSearchKeyWordMappingMulti(classifyName, chartPermissionIdList, classify.Id)
+	if err != nil {
+		errMsg = "修改分类权限失败"
+		return
+	}
+
+	// 修改CRM权限
+	go func() {
+		_ = EditClassifyChartPermissionSync(classifyName, classify.Id)
+	}()
+
+	// 如果父级分类不为空的话,那么就标记有子级分类,同时
+	if parentClassifyItem != nil {
+		parentClassifyItem.HasChild = 1
+		parentClassifyItem.UpdateClassify([]string{"HasChild"})
+
+		// 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系)
+		if childClassifyCount <= 0 {
+			// 继承父级分类下的章节类型(创建新的章节与分类的关系)
+			tmpErr := inheritReportChapterType(parentId, classify.Id)
+			if tmpErr != nil {
+				return
+			}
+
+			moveReportByAddClassify(parentClassifyItem, classify)
+		}
+	}
+
+	return
+}
+
+// 关于研报分类,因只允许报告或品种关联在最小分类下,所以当某个父分类(非三级分类)已关联报告或品种,需要在该父分类下增加子分类,则第一个子分类添加成功时,默认把该父分类关联的品种和报告转移至新创建的子分类(第一个子分类)下
+// moveReportByAddClassify
+// @Description: 报告和章节的转移
+// @author: Roc
+// @datetime 2024-06-17 16:29:56
+// @param parentClassifyInfo *models.Classify
+// @param currClassifyInfo *models.Classify
+// @return err error
+func moveReportByAddClassify(parentClassifyInfo, currClassifyInfo *models.Classify) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error(fmt.Sprint("历史报告更改分类失败,父级分类ID:", parentClassifyInfo.Id, ";当前分类ID:", currClassifyInfo.Id, ";错误信息:", err.Error()))
+		}
+	}()
+	if currClassifyInfo.Level > 3 {
+		err = errors.New("父级分类不支持三级分类以上")
+		return
+	}
+
+	// 报告的分类归属调整,转为下一级的分类
+
+	var condition, updateStr string
+	pars := make([]interface{}, 0)
+	switch currClassifyInfo.Level {
+	case 3: // 当前分类是3级分类
+		updateStr += ` classify_id_third = ?,classify_name_third = ?`
+		condition += ` AND classify_id_second = ? `
+	case 2: // 当前分类是2级分类
+		updateStr += ` classify_id_second = ?,classify_name_second = ?`
+		condition += ` AND classify_id_first = ? `
+	default:
+		err = errors.New("错误的分类层级")
+		return
+	}
+
+	pars = append(pars, currClassifyInfo.Id, currClassifyInfo.ClassifyName, parentClassifyInfo.Id)
+
+	// 获取当前分类下的所有章节类型
+	currReportChapterTypeList, err := models.GetReportChapterTypeListByClassifyId(currClassifyInfo.Id)
+	if err != nil {
+		return
+	}
+	// 当前的章节类型ID ---> 继承的章节类型ID
+	chapterTypeIdMap := make(map[int]int)
+	for _, v := range currReportChapterTypeList {
+		chapterTypeIdMap[v.ReportChapterTypeId] = v.InheritReportChapterTypeId
+	}
+
+	// 报告转移后,历史章节报告中的type_id也要修复成最新的type_id
+	err = models.ModifyReportClassifyAndReportChapterTypeByCondition(condition, pars, updateStr, chapterTypeIdMap, parentClassifyInfo.Id, currClassifyInfo.Id, currClassifyInfo.ClassifyName)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// inheritReportChapterType
+// @Description: 继承父级分类下的章节类型
+// @author: Roc
+// @datetime 2024-06-17 14:41:04
+// @param parentClassifyId int
+// @param currClassifyId int
+// @return err error
+func inheritReportChapterType(parentClassifyId, currClassifyId int) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error(fmt.Sprint("继承父级分类下的章节类型失败,父级分类ID:", parentClassifyId, ";当前分类ID:", currClassifyId, ";错误信息:", err.Error()))
+		}
+	}()
+	parentReportChapterTypeList, err := models.GetReportChapterTypeListByClassifyId(parentClassifyId)
+	if err != nil {
+		return
+	}
+
+	// 如果没有章节类型,那么就直接返回
+	if len(parentReportChapterTypeList) <= 0 {
+		return
+	}
+
+	addList := make([]*models.ReportChapterType, 0)
+	for _, v := range parentReportChapterTypeList {
+		addList = append(addList, &models.ReportChapterType{
+			//ReportChapterTypeId:        0,
+			ReportChapterTypeKey:       v.ReportChapterTypeKey,
+			ReportChapterTypeThumb:     v.ReportChapterTypeThumb,
+			BannerUrl:                  v.BannerUrl,
+			ReportChapterTypeName:      v.ReportChapterTypeName,
+			Sort:                       v.Sort,
+			Enabled:                    v.Enabled,
+			CreatedTime:                time.Now(),
+			LastUpdatedTime:            time.Now(),
+			ResearchType:               v.ResearchType,
+			SelectedImage:              v.SelectedImage,
+			UnselectedImage:            v.UnselectedImage,
+			PcSelectedImage:            v.PcSelectedImage,
+			PcUnselectedImage:          v.PcUnselectedImage,
+			EditImgUrl:                 v.EditImgUrl,
+			TickerTitle:                v.TickerTitle,
+			IsShow:                     v.IsShow,
+			PauseStartTime:             v.PauseStartTime,
+			PauseEndTime:               v.PauseEndTime,
+			IsSet:                      v.IsSet,
+			YbIconUrl:                  v.YbIconUrl,
+			YbBottomIcon:               v.YbBottomIcon,
+			ReportClassifyId:           currClassifyId,
+			InheritReportChapterTypeId: v.ReportChapterTypeId,
+		})
+	}
+
+	obj := models.ReportChapterType{}
+	err = obj.MultiCreate(addList)
+
+	return
+}
+
+// EditReportClassify
+// @Description: 编辑报告分类
+// @author: Roc
+// @datetime 2024-06-17 13:31:33
+// @param classifyId int
+// @param classifyName string
+// @param chartPermissionIdList []int
+// @return err error
+// @return errMsg string
+// @return isSendEmail bool
+func EditReportClassify(classifyId int, classifyName string, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+	errMsg = `修改失败`
+
+	item, err := models.GetClassifyById(classifyId)
+	if err != nil {
+		errMsg = "获取分类信息失败"
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在, 或已被删除"
+			isSendEmail = false
+		}
+		return
+	}
+	originName := item.ClassifyName
+
+	// 重名校验
+	existName, e := models.GetClassifyByName(classifyName, item.ParentId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		errMsg = "获取信息失败"
+		err = errors.New("获取重名分类失败, Err: " + err.Error())
+		return
+	}
+	if existName != nil && existName.Id != item.Id {
+		errMsg = "分类名称:" + classifyName + "已存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	item.ClassifyName = classifyName
+
+	// ETA1.8.3:不允许修改上级分类  2024-6-17 13:21:01
+	//item.ParentId = req.ParentId
+	item.ModifyTime = time.Now().Local()
+	cols := make([]string, 0)
+	cols = append(cols, "ClassifyName", "ModifyTime")
+	err = item.UpdateClassify(cols)
+	if err != nil {
+		return
+	}
+
+	err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, chartPermissionIdList, item.Id)
+	if err != nil {
+		errMsg = "修改分类权限失败"
+		return
+	}
+
+	// 修改CRM权限
+	go func() {
+		_ = EditClassifyChartPermissionSync(item.ClassifyName, item.Id)
+	}()
+
+	// TODO 修改分类的关联品种时,历史报告中关联的品种怎么处理?
+	// 更新报告分类名称/父级分类后
+	go func() {
+		_ = AfterUpdateClassifyNameOrParent(item.Id, item.ParentId, item.ParentId, originName, item.ClassifyName)
+	}()
+
+	return
+}

+ 16 - 18
services/report_v2.go

@@ -294,6 +294,16 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
 		return
 	}
 
+	// 最小单元的分类
+	var minClassifyName string
+	if reportInfo.ClassifyIdThird == minClassifyId {
+		minClassifyName = reportInfo.ClassifyNameThird
+	} else if reportInfo.ClassifyIdSecond == minClassifyId {
+		minClassifyName = reportInfo.ClassifyNameSecond
+	} else {
+		minClassifyName = reportInfo.ClassifyNameFirst
+	}
+
 	// TODO 弘则得单独处理启用禁用的情况
 	//if utils.BusinessCode != utils.BusinessCodeRelease && utils.BusinessCode != utils.BusinessCodeSandbox && utils.BusinessCode != utils.BusinessCodeDebug {
 	//	br.Ret = 200
@@ -379,12 +389,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
 			// 自定义的报告内容
 			customChapter.ReportId = reportInfo.Id
 			customChapter.ReportChapterId = 0
-			customChapter.ClassifyIdFirst = reportInfo.ClassifyIdFirst
-			customChapter.ClassifyNameFirst = reportInfo.ClassifyNameFirst
-			customChapter.ClassifyIdSecond = reportInfo.ClassifyIdSecond
-			customChapter.ClassifyNameSecond = reportInfo.ClassifyNameSecond
-			customChapter.ClassifyIdThird = reportInfo.ClassifyIdThird
-			customChapter.ClassifyNameThird = reportInfo.ClassifyNameThird
+			customChapter.ClassifyIdFirst = minClassifyId
+			customChapter.ClassifyNameFirst = minClassifyName
 			customChapter.Stage = reportInfo.Stage
 			customChapter.PublishState = 1
 			customChapter.CreateTime = reportInfo.CreateTime
@@ -410,12 +416,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
 			chapterItem.AddType = 2
 			chapterItem.Title = v.Title
 			chapterItem.ReportType = v.ReportType
-			chapterItem.ClassifyIdFirst = reportInfo.ClassifyIdFirst
-			chapterItem.ClassifyNameFirst = reportInfo.ClassifyNameFirst
-			chapterItem.ClassifyIdSecond = reportInfo.ClassifyIdSecond
-			chapterItem.ClassifyNameSecond = reportInfo.ClassifyNameSecond
-			chapterItem.ClassifyIdThird = reportInfo.ClassifyIdThird
-			chapterItem.ClassifyNameThird = reportInfo.ClassifyNameThird
+			chapterItem.ClassifyIdFirst = minClassifyId
+			chapterItem.ClassifyNameFirst = minClassifyName
 			chapterItem.TypeId = typeItem.ReportChapterTypeId
 			chapterItem.TypeName = typeItem.ReportChapterTypeName
 			chapterItem.Content = v.Content
@@ -436,12 +438,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
 			chapterItem.AddType = 1
 			chapterItem.Title = typeItem.ReportChapterTypeName
 			//chapterItem.ReportType = reportType
-			chapterItem.ClassifyIdFirst = reportInfo.ClassifyIdFirst
-			chapterItem.ClassifyNameFirst = reportInfo.ClassifyNameFirst
-			chapterItem.ClassifyIdSecond = reportInfo.ClassifyIdSecond
-			chapterItem.ClassifyNameSecond = reportInfo.ClassifyNameSecond
-			chapterItem.ClassifyIdThird = reportInfo.ClassifyIdThird
-			chapterItem.ClassifyNameThird = reportInfo.ClassifyNameThird
+			chapterItem.ClassifyIdFirst = minClassifyId
+			chapterItem.ClassifyNameFirst = minClassifyName
 			chapterItem.TypeId = typeItem.ReportChapterTypeId
 			chapterItem.TypeName = typeItem.ReportChapterTypeName
 			chapterItem.Stage = reportInfo.Stage