瀏覽代碼

Merge branch 'eta/1.8.3'

Roc 9 月之前
父節點
當前提交
03a76ebf35

+ 74 - 11
controllers/report.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"github.com/beego/beego/v2/server/web"
 	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/company"
 	"hongze/hz_crm_api/services"
 	"hongze/hz_crm_api/services/alarm_msg"
 	"hongze/hz_crm_api/utils"
@@ -60,6 +61,21 @@ func (this *ReportController) GetDayWeekReportChapterTypeList() {
 		return
 	}
 
+	dayClassifyId, err := company.GetReportClassifyIdByConfigKey("report_day_classify_id")
+	if err != nil {
+		br.Msg = "获取晨报ID配置失败"
+		br.ErrMsg = "获取配置失败"
+		br.IsSendEmail = false
+		return
+	}
+	weekClassifyId, err := company.GetReportClassifyIdByConfigKey("report_week_classify_id")
+	if err != nil {
+		br.Msg = "获取周报ID配置失败"
+		br.ErrMsg = "获取配置失败"
+		br.IsSendEmail = false
+		return
+	}
+
 	dayList := make([]*models.ReportChapterType, 0)
 	weekList := make([]*models.ReportChapterType, 0)
 
@@ -68,8 +84,8 @@ func (this *ReportController) GetDayWeekReportChapterTypeList() {
 		tmpCondition := condition
 		tmpPars := pars
 		// 报告类型
-		tmpCondition += ` AND research_type = ? `
-		tmpPars = append(tmpPars, "day")
+		tmpCondition += ` AND report_classify_id = ? `
+		tmpPars = append(tmpPars, dayClassifyId)
 
 		list, err := models.GetAllReportChapterTypeList(tmpCondition, tmpPars)
 		if err != nil {
@@ -87,6 +103,13 @@ func (this *ReportController) GetDayWeekReportChapterTypeList() {
 					v.PauseEndTime = ``
 				}
 			}
+			if v.PauseStartTime == `0001-01-01` {
+				v.PauseStartTime = ``
+			}
+			if v.PauseEndTime == `0001-01-01` {
+				v.PauseEndTime = ``
+			}
+
 			dayList = append(dayList, v)
 		}
 	}
@@ -96,8 +119,8 @@ func (this *ReportController) GetDayWeekReportChapterTypeList() {
 		tmpCondition := condition
 		tmpPars := pars
 		// 报告类型
-		tmpCondition += ` AND research_type = ? `
-		tmpPars = append(tmpPars, "week")
+		tmpCondition += ` AND report_classify_id = ? `
+		tmpPars = append(tmpPars, weekClassifyId)
 
 		list, err := models.GetAllReportChapterTypeList(tmpCondition, tmpPars)
 		if err != nil {
@@ -115,6 +138,13 @@ func (this *ReportController) GetDayWeekReportChapterTypeList() {
 					v.PauseEndTime = ``
 				}
 			}
+			if v.PauseStartTime == `0001-01-01` {
+				v.PauseStartTime = ``
+			}
+			if v.PauseEndTime == `0001-01-01` {
+				v.PauseEndTime = ``
+			}
+			
 			weekList = append(weekList, v)
 		}
 	}
@@ -196,8 +226,26 @@ func (this *ReportController) SetDayWeekReportUpdateRule() {
 		return
 	}
 
+	classifyIdKey := ``
+	switch researchType {
+	case "day":
+		classifyIdKey = `report_day_classify_id`
+	case "week":
+		classifyIdKey = `report_week_classify_id`
+	default:
+		br.Msg = "报告类型异常"
+		return
+	}
+	reportClassifyId, err := company.GetReportClassifyIdByConfigKey(classifyIdKey)
+	if err != nil {
+		br.Msg = "获取分类ID配置失败"
+		br.ErrMsg = "获取配置失败,key:" + classifyIdKey
+		br.IsSendEmail = false
+		return
+	}
+
 	// 设置章节类型的暂停时间
-	if err := models.SetDayWeekReportUpdateRule(researchType, req.List); err != nil {
+	if err := models.SetDayWeekReportUpdateRule(reportClassifyId, req.List); err != nil {
 		br.Msg = "设置暂停时间失败"
 		br.ErrMsg = "设置暂停时间失败, Err: " + err.Error()
 		return
@@ -205,7 +253,7 @@ func (this *ReportController) SetDayWeekReportUpdateRule() {
 	// 同步eta系统的章节更新配置
 	go func() {
 		ruleSyncReq := new(services.EditReportChapterTypeRuleSyncReq)
-		ruleSyncReq.ResearchType = researchType
+		ruleSyncReq.ReportClassifyId = reportClassifyId
 		_, _ = services.EditReportChapterTypeRuleSync(ruleSyncReq)
 	}()
 
@@ -301,24 +349,39 @@ func (this *ReportController) GetStopDayWeekReportChapterTypeList() {
 		return
 	}
 
+	dayClassifyId, err := company.GetReportClassifyIdByConfigKey("report_day_classify_id")
+	if err != nil {
+		br.Msg = "获取晨报ID配置失败"
+		br.ErrMsg = "获取配置失败"
+		br.IsSendEmail = false
+		return
+	}
+	weekClassifyId, err := company.GetReportClassifyIdByConfigKey("report_week_classify_id")
+	if err != nil {
+		br.Msg = "获取周报ID配置失败"
+		br.ErrMsg = "获取配置失败"
+		br.IsSendEmail = false
+		return
+	}
+
 	for _, v := range stopList {
-		if v.ResearchType == "day" {
+		if v.ReportClassifyId == dayClassifyId {
 			stopDay = append(stopDay, v)
-		} else {
+		} else if v.ReportClassifyId == weekClassifyId {
 			stopWeek = append(stopWeek, v)
 		}
 	}
 
-	disableList, err := models.GetDisableUpdateReportChapterTypeListByResearchType()
+	disableList, err := models.GetDisableUpdateReportChapterTypeListByResearchTypeByClassifyIdList([]int{dayClassifyId, weekClassifyId})
 	if err != nil {
 		br.Msg = "获取停止更新报告章节类型列表失败"
 		br.ErrMsg = "获取停止更新报告章节类型列表失败, Err: " + err.Error()
 		return
 	}
 	for _, v := range disableList {
-		if v.ResearchType == "day" {
+		if v.ReportClassifyId == dayClassifyId {
 			disableDay = append(disableDay, v)
-		} else {
+		} else if v.ReportClassifyId == weekClassifyId {
 			disableWeek = append(disableWeek, v)
 		}
 	}

+ 6 - 7
controllers/report_chapter_type.go

@@ -15,7 +15,7 @@ type ReportChapterTypeController struct {
 // List
 // @Title 报告章节列表
 // @Description 报告章节列表
-// @Param   ReportType  query  string  true  "报告类型: day-晨报; week-周报"
+// @Param   ClassifyId  query  int  true  "所属分类id"
 // @Success 200 {object} models.ReportChapterTypePageListResp
 // @router /chapter_type/list [get]
 func (this *ReportChapterTypeController) List() {
@@ -32,16 +32,15 @@ func (this *ReportChapterTypeController) List() {
 		br.Ret = 408
 		return
 	}
-	reportType := this.GetString("ReportType")
-	typeArr := []string{utils.REPORT_TYPE_DAY, utils.REPORT_TYPE_WEEK}
-	if !utils.InArrayByStr(typeArr, reportType) {
-		br.Msg = "请选择报告类型"
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	if classifyId <= 0 {
+		br.Msg = "请选择分类"
 		return
 	}
 
-	cond := ` AND research_type = ?`
+	cond := ` AND report_classify_id = ?`
 	pars := make([]interface{}, 0)
-	pars = append(pars, reportType)
+	pars = append(pars, classifyId)
 	list, e := models.GetReportChapterTypePageList(cond, pars)
 	if e != nil {
 		br.Msg = "获取失败"

+ 115 - 53
controllers/yb/road_video.go

@@ -11,7 +11,6 @@ import (
 	"hongze/hz_crm_api/services"
 	"hongze/hz_crm_api/services/yb"
 	"hongze/hz_crm_api/utils"
-	"sort"
 	"strings"
 	"time"
 )
@@ -421,55 +420,64 @@ func (r *RoadVideoController) TwoWeekClassifyList() {
 	}
 
 	// 2023-04-19 取classify表relate_video=1的二级分类, 但是需要分层级, 所以对应的一级分类也要组合起来
-	list, e := models.GetAllClassify()
+	list, e := models.GetAllClassifyByRelateVideo()
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error()
 		return
 	}
-	resp := make([]*models.SimpleClassifyList, 0)
-	parentMap := make(map[int]*models.SimpleClassifyList)
-	classifyMap := make(map[int]*models.Classify)
-	for _, c := range list {
-		classifyMap[c.Id] = c
-		if c.ParentId > 0 && c.RelateVideo == 1 {
-			if parentMap[c.ParentId] == nil {
-				parentMap[c.ParentId] = new(models.SimpleClassifyList)
+
+	// 获取父级的分类
+	{
+		idMap := make(map[int]bool)
+
+		currParentClassifyIdList := make([]int, 0)
+		for _, v := range list {
+			idMap[v.Id] = true
+			if v.ParentId > 0 {
+				currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId)
 			}
 		}
-	}
-	for k, v := range parentMap {
-		p := classifyMap[k]
-		if p == nil {
-			continue
+
+		findList := list
+		list = make([]*models.Classify, 0)
+
+		tmpList, tmpErr := services.GetParentClassifyListByParentIdList(currParentClassifyIdList)
+		if tmpErr != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取上级分类信息失败,Err:" + tmpErr.Error()
+			return
 		}
-		v.Id = p.Id
-		v.ClassifyName = p.ClassifyName
-		v.Sort = p.Sort
-		v.Child = make([]*models.SimpleClassifyList, 0)
-		for _, c := range list {
-			if c.ParentId == v.Id && c.RelateVideo == 1 {
-				v.Child = append(v.Child, &models.SimpleClassifyList{
-					Id:           c.Id,
-					ClassifyName: c.ClassifyName,
-					ParentId:     c.ParentId,
-					Sort:         c.Sort,
-				})
+		for _, v := range tmpList {
+			if _, ok := idMap[v.Id]; !ok {
+				list = append(list, v)
 			}
 		}
-		sort.Slice(v.Child, func(i, j int) bool {
-			return v.Child[j].Sort > v.Child[i].Sort
+
+		list = append(list, findList...)
+	}
+
+	allList := make([]*models.SimpleClassifyList, 0)
+	for _, v := range list {
+		allList = append(allList, &models.SimpleClassifyList{
+			Id:           v.Id,
+			ClassifyName: v.ClassifyName,
+			ParentId:     v.ParentId,
+			Sort:         v.Sort,
+			CreateTime:   v.CreateTime,
+			Child:        make([]*models.SimpleClassifyList, 0),
 		})
-		resp = append(resp, v)
 	}
-	sort.Slice(resp, func(i, j int) bool {
-		return resp[j].Sort > resp[i].Sort
-	})
+
+	// 先将分类列表排序
+	services.SortClassifyListBySortAndCreateTime(allList)
+	// 接着转换结构
+	allList = services.GetClassifyListTreeRecursive(allList, 0)
 
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
-	br.Data = resp
+	br.Data = allList
 }
 
 // SimpleReportList
@@ -498,7 +506,8 @@ func (r *RoadVideoController) SimpleReportList() {
 	classifyIdSecond, _ := r.GetInt("ClassifyIdSecond", 0)
 	if classifyIdSecond <= 0 {
 		// 2023-03-03 直接取classify表relate_video=1的二级分类下的报告
-		classifyCond := ` AND parent_id > 0 AND relate_video = 1`
+		//classifyCond := ` AND parent_id > 0 AND relate_video = 1`
+		classifyCond := ` AND relate_video = 1`
 		classifyPars := make([]interface{}, 0)
 		classifyList, e := models.GetClassifyByCondition(classifyCond, "", classifyPars)
 		if e != nil {
@@ -506,28 +515,68 @@ func (r *RoadVideoController) SimpleReportList() {
 			br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error()
 			return
 		}
-		classifyIds := make([]int, 0)
+		var hasChild bool
+		firstClassifyIds := make([]int, 0)
+		secondClassifyIds := make([]int, 0)
+		thirdClassifyIds := make([]int, 0)
 		for _, c := range classifyList {
-			classifyIds = append(classifyIds, c.Id)
+			switch c.Level {
+			case 1:
+				firstClassifyIds = append(firstClassifyIds, c.Id)
+				hasChild = true
+			case 2:
+				secondClassifyIds = append(secondClassifyIds, c.Id)
+				hasChild = true
+			case 3:
+				thirdClassifyIds = append(thirdClassifyIds, c.Id)
+				hasChild = true
+			}
 		}
-		if len(classifyIds) > 0 {
-			cond += ` AND classify_id_second IN ( ` + utils.GetOrmInReplace(len(classifyIds)) + ` ) `
-			pars = append(pars, classifyIds)
+		if hasChild {
+			classifyCondList := make([]string, 0)
+			if len(firstClassifyIds) > 0 {
+				classifyCondList = append(classifyCondList, ` classify_id_first IN ( `+utils.GetOrmInReplace(len(firstClassifyIds))+` ) `)
+				pars = append(pars, firstClassifyIds)
+			}
+			if len(secondClassifyIds) > 0 {
+				classifyCondList = append(classifyCondList, ` classify_id_second IN ( `+utils.GetOrmInReplace(len(secondClassifyIds))+` ) `)
+				pars = append(pars, secondClassifyIds)
+			}
+			if len(thirdClassifyIds) > 0 {
+				classifyCondList = append(classifyCondList, ` classify_id_third IN ( `+utils.GetOrmInReplace(len(thirdClassifyIds))+` ) `)
+				pars = append(pars, thirdClassifyIds)
+			}
+			cond += fmt.Sprintf(` AND (%s) `, strings.Join(classifyCondList, " OR "))
 		} else {
 			cond += ` AND 1 = 2`
 		}
+	} else {
+		classifyItem, err := models.GetClassifyById(classifyIdSecond)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类失败, Err: " + err.Error()
+			return
+		}
+		switch classifyItem.Level {
+		case 1:
+			cond += ` AND classify_id_first = ? `
+			pars = append(pars, classifyIdSecond)
+		case 2:
+			cond += ` AND classify_id_second = ? `
+			pars = append(pars, classifyIdSecond)
+		case 3:
+			cond += ` AND classify_id_third = ? `
+			pars = append(pars, classifyIdSecond)
+		}
 	}
-	if classifyIdSecond > 0 {
-		cond += ` AND classify_id_second = ? `
-		pars = append(pars, classifyIdSecond)
-	}
+
 	keyword := r.GetString("Keyword", "")
 	if keyword != "" {
 		kw := fmt.Sprint("%", keyword, "%")
 		cond += ` AND title LIKE ?`
 		pars = append(pars, kw)
 	}
-	fieldArr := []string{"id", "classify_id_second", "title", "publish_time"}
+	fieldArr := []string{"id", "classify_id_first", "classify_id_second", "classify_id_third", "title", "publish_time"}
 	orderRule := ` ORDER BY publish_time DESC, id DESC`
 	reports, e := models.GetReportByCondition(cond, pars, fieldArr, orderRule, true, 0, 5)
 	if e != nil {
@@ -541,10 +590,16 @@ func (r *RoadVideoController) SimpleReportList() {
 	{
 		classifyIds := make([]int, 0)
 		for _, v := range reports {
-			if utils.InArrayByInt(classifyIds, v.ClassifyIdSecond) {
+			minClassifyId, _, e := services.GetMinClassify(v)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error()
+				return
+			}
+			if utils.InArrayByInt(classifyIds, minClassifyId) {
 				continue
 			}
-			classifyIds = append(classifyIds, v.ClassifyIdSecond)
+			classifyIds = append(classifyIds, minClassifyId)
 		}
 		if len(classifyIds) > 0 {
 			classifyIdsPermissions, e := models.GetPermissionsByClassifyIds(classifyIds)
@@ -588,13 +643,20 @@ func (r *RoadVideoController) SimpleReportList() {
 		}
 
 		for i := range reports {
+			tmpReport := reports[i]
+			minClassifyId, _, e := services.GetMinClassify(tmpReport)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error()
+				return
+			}
 			respList = append(respList, &SimpleReportListResp{
-				ReportId:       reports[i].Id,
-				Title:          reports[i].Title,
-				PublishTime:    reports[i].PublishTime.Format(utils.FormatDateTime),
-				BindVideo:      bindMap[reports[i].Id],
-				BindVideoTitle: bindTitleMap[reports[i].Id],
-				PermissionIds:  classifyPermissions[reports[i].ClassifyIdSecond],
+				ReportId:       tmpReport.Id,
+				Title:          tmpReport.Title,
+				PublishTime:    tmpReport.PublishTime.Format(utils.FormatDateTime),
+				BindVideo:      bindMap[tmpReport.Id],
+				BindVideoTitle: bindTitleMap[tmpReport.Id],
+				PermissionIds:  classifyPermissions[minClassifyId],
 			})
 		}
 	}

+ 73 - 5
models/classify.go

@@ -39,6 +39,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"`
 }
 
 func GetClassifyById(classifyId int) (item *Classify, err error) {
@@ -83,7 +85,38 @@ type ClassifyItem struct {
 }
 
 type ClassifyListResp struct {
-	List []*ClassifyList
+	List []*ClassifyListV2
+}
+type ClassifyListV2 struct {
+	Id                    int               `orm:"column(id);pk"`
+	ClassifyName          string            `description:"分类名称"`
+	Sort                  int               `description:"排序"`
+	ParentId              int               `description:"父级分类id"`
+	CreateTime            time.Time         `description:"创建时间"`
+	ModifyTime            time.Time         `description:"修改时间"`
+	Abstract              string            `description:"简介"`
+	Descript              string            `description:"描述"`
+	ClassifyLabel         string            `description:"分类标签"`
+	ShowType              int               `description:"展示类型:1-列表 2-专栏"`
+	HasTeleconference     int               `description:"是否有电话会:0-否 1-是"`
+	IsShow                int               `description:"是否在小程序显示:1-显示 0-隐藏"`
+	YbFiccSort            int               `description:"小程序FICC页排序"`
+	YbFiccIcon            string            `description:"小程序FICC页icon"`
+	YbFiccPcIcon          string            `description:"小程序PC端FICC页背景图"`
+	YbIconUrl             string            `description:"小程序已购页icon"`
+	YbBgUrl               string            `description:"小程序已购详情背景图"`
+	YbListImg             string            `description:"小程序研报列表封面图"`
+	YbShareBgImg          string            `description:"小程序研报详情分享背景图"`
+	YbRightBanner         string            `description:"Pc端详情页,右侧,报告合集背景图"`
+	RelateTel             int               `description:"是否在电话会中可选: 0-否; 1-是"`
+	RelateVideo           int               `description:"是否在路演视频中可选: 0-否; 1-是"`
+	Enabled               int               `description:"是否可用,1可用,0禁用"`
+	Child                 []*ClassifyListV2 `gorm:"-"`
+	ClassifyMenuId        int               `description:"二级分类-子目录ID"`
+	ClassifyMenuList      []*ClassifyMenu   `gorm:"-"`
+	ChartPermissionIdList []int             `description:"绑定的权限ID" gorm:"-"`
+	Level                 int               `description:"层级"`
+	HasChild              int               `description:"是否有子级别,0:下面没有子分类,1:下面有子分类;默认:0"`
 }
 
 // 获取分类列表
@@ -178,10 +211,12 @@ func GetAllClassify() (list []*Classify, err error) {
 
 // SimpleClassifyList 简版分类列表
 type SimpleClassifyList struct {
-	Id           int    `description:"分类ID"`
-	ClassifyName string `description:"分类名称"`
-	ParentId     int    `description:"父级ID"`
-	Sort         int    `description:"排序"`
+	Id           int       `description:"分类ID"`
+	ClassifyName string    `description:"分类名称"`
+	ParentId     int       `description:"父级ID"`
+	Sort         int       `description:"排序"`
+	CreateTime   time.Time `description:"创建时间"`
+	Level        int       `description:"层级"`
 	Child        []*SimpleClassifyList
 }
 
@@ -200,3 +235,36 @@ func GetClassifyByCondition(condition, orderRule string, pars []interface{}) (it
 	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
+
+// GetAllClassifyByRelateVideo
+// @Description: 获取关联视频的所有分类
+// @author: Roc
+// @datetime 2024-07-12 17:19:06
+// @return list []*Classify
+// @return err error
+func GetAllClassifyByRelateVideo() (list []*Classify, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM classify where relate_video = 1`
+	_, err = o.Raw(sql).QueryRows(&list)
+	return
+}
+
+// GetClassifyListByParentIdList
+// @Description: 获取分类列表
+// @author: Roc
+// @datetime 2024-06-19 09:49:33
+// @param keyWord string
+// @param enabled int
+// @return items []*ClassifyList
+// @return err error
+func GetClassifyListByParentIdList(parentClassifyIdList []int) (items []*Classify, err error) {
+	num := len(parentClassifyIdList)
+	if num <= 0 {
+		return
+	}
+	sql := `SELECT * FROM classify WHERE id in (` + utils.GetOrmInReplace(num) + `) ORDER BY sort ASC, create_time ASC`
+
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Raw(sql, parentClassifyIdList).QueryRows(&items)
+	return
+}

+ 47 - 2
models/company/company_config.go

@@ -1,7 +1,10 @@
 package company
 
 import (
+	"encoding/json"
+	"errors"
 	"github.com/beego/beego/v2/client/orm"
+	"hongze/hz_crm_api/utils"
 )
 
 const (
@@ -9,11 +12,10 @@ const (
 )
 
 type CrmConfig struct {
-	ConfigCode   string `description:"详情Code"`
+	ConfigCode  string `description:"详情Code"`
 	ConfigValue string `description:"详情"`
 }
 
-
 func GetConfigValueByCode(configCode string) (total int, err error) {
 	o := orm.NewOrm()
 	sql := ` SELECT config_value FROM crm_config WHERE config_code=? `
@@ -29,9 +31,52 @@ func CrmConfigUpdate(newValue, configCode string) (err error) {
 	return
 }
 
+// ConfigClassifyId
+// @Description: 后台配置的报告id
+type ConfigClassifyId struct {
+	Debug   int `json:"debug"`
+	Release int `json:"release"`
+}
+
 func GetConfigDetailByCode(configCode string) (item CrmConfig, err error) {
 	o := orm.NewOrm()
 	sql := ` SELECT * FROM crm_config WHERE config_code=? `
 	err = o.Raw(sql, configCode).QueryRow(&item)
 	return
 }
+
+// GetReportClassifyIdByConfigKey
+// @Description: 获取关联的报告id
+// @author: Roc
+// @datetime 2024-06-18 14:10:27
+// @param configKey string
+// @return classifyId int
+// @return err error
+func GetReportClassifyIdByConfigKey(configKey string) (classifyId int, err error) {
+	// 别问为啥要从配置里拿=_=!
+	conf, e := GetConfigDetailByCode(configKey)
+	if e != nil {
+		err = errors.New("获取配置的id失败, Err: " + e.Error())
+		return
+	}
+	if conf.ConfigValue == "" {
+		err = errors.New("ID配置有误")
+		return
+	}
+	type TwoWeekIdConf struct {
+		Debug   []int
+		Release []int
+	}
+	classifyIdConf := new(ConfigClassifyId)
+	if e = json.Unmarshal([]byte(conf.ConfigValue), &classifyIdConf); e != nil {
+		err = errors.New("解析ID配置失败, Err: " + e.Error())
+		return
+	}
+	if utils.RunMode == "debug" {
+		classifyId = classifyIdConf.Debug
+	} else {
+		classifyId = classifyIdConf.Release
+	}
+
+	return
+}

+ 7 - 0
models/report.go

@@ -40,6 +40,13 @@ type Report struct {
 	MsgSendTime        time.Time `description:"模版消息发送时间"`
 	AdminId            int       `description:"创建者账号"`
 	AdminRealName      string    `description:"创建者姓名"`
+	ClassifyIdThird    int       `description:"三级分类id"`
+	ClassifyNameThird  string    `description:"三级分类名称"`
+	CollaborateType    int8      `description:"协作方式,1:个人,2:多人协作。默认:1"`
+	ReportLayout       int8      `description:"报告布局,1:常规布局,2:智能布局。默认:1"`
+	IsPublicPublish    int8      `description:"是否公开发布,1:是,2:否"`
+	ReportCreateTime   time.Time `description:"报告时间创建时间"`
+	InheritReportId    int       `description:"待继承的报告ID"`
 }
 
 type ReportList struct {

+ 48 - 27
models/report_chapter_type.go

@@ -7,28 +7,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"`
+	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 (item *ReportChapterType) Create() (err error) {
@@ -183,7 +185,7 @@ func ResetDayWeekReportUpdateRule(researchType string) (err error) {
 }
 
 // SetDayWeekReportUpdateRule 设置章节类型的暂停时间
-func SetDayWeekReportUpdateRule(researchType string, list []DayWeekReportUpdateRule) (err error) {
+func SetDayWeekReportUpdateRule(classifyId int, list []DayWeekReportUpdateRule) (err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	if err != nil {
@@ -198,8 +200,8 @@ func SetDayWeekReportUpdateRule(researchType string, list []DayWeekReportUpdateR
 	}()
 
 	// 先将所有品种的状态变更为启用
-	sql := ` UPDATE report_chapter_type SET pause_start_time = null, pause_end_time = null, is_set = 0 WHERE research_type = ?`
-	_, err = to.Raw(sql, researchType).Exec()
+	sql := ` UPDATE report_chapter_type SET pause_start_time = null, pause_end_time = null, is_set = 0 WHERE report_classify_id = ?`
+	_, err = to.Raw(sql, classifyId).Exec()
 	if err != nil {
 		return
 	}
@@ -208,8 +210,8 @@ func SetDayWeekReportUpdateRule(researchType string, list []DayWeekReportUpdateR
 		if v.PauseStartTime == `` || v.PauseEndTime == `` {
 			continue
 		}
-		tmpSql := ` UPDATE report_chapter_type SET pause_start_time = ?, pause_end_time = ?, is_set = 1 WHERE research_type = ? AND report_chapter_type_id = ? `
-		_, err = to.Raw(tmpSql, v.PauseStartTime, v.PauseEndTime, researchType, v.ReportChapterTypeId).Exec()
+		tmpSql := ` UPDATE report_chapter_type SET pause_start_time = ?, pause_end_time = ?, is_set = 1 WHERE report_classify_id = ? AND report_chapter_type_id = ? `
+		_, err = to.Raw(tmpSql, v.PauseStartTime, v.PauseEndTime, classifyId, v.ReportChapterTypeId).Exec()
 		if err != nil {
 			return
 		}
@@ -292,6 +294,25 @@ func GetDisableUpdateReportChapterTypeListByResearchType() (list []*ReportChapte
 	return
 }
 
+// GetDisableUpdateReportChapterTypeListByResearchTypeByClassifyIdList
+// @Description: 根据分类id列表获取停止更新的章节类型列表
+// @author: Roc
+// @datetime 2024-06-18 14:13:50
+// @param classifyIdList []int
+// @return list []*ReportChapterType
+// @return err error
+func GetDisableUpdateReportChapterTypeListByResearchTypeByClassifyIdList(classifyIdList []int) (list []*ReportChapterType, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM report_chapter_type WHERE enabled = 0 AND report_classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&list)
+
+	return
+}
+
 // UpdateReportChapterTypeResp 停止更新的报告分类列表
 type UpdateReportChapterTypeResp struct {
 	Day  []*ReportChapterType `description:"所有晨报品种"`

+ 87 - 0
services/classify.go

@@ -7,6 +7,7 @@ import (
 	"hongze/hz_crm_api/utils"
 	"io/ioutil"
 	"net/http"
+	"sort"
 	"strings"
 )
 
@@ -182,3 +183,89 @@ type GetClassifyListResp struct {
 	Data   models.ClassifyListResp `json:"data" description:"返回数据"`
 	ErrMsg string                  `json:"-" description:"错误信息,不用返回给前端,只是做日志记录"`
 }
+
+// GetParentClassifyListByParentIdList
+// @Description: 递归获取父级分类信息,正常来讲只有三次
+// @author: Roc
+// @datetime 2024-06-19 13:23:33
+// @param parentClassifyIdList []int
+// @return list []*models.ClassifyList
+// @return err error
+func GetParentClassifyListByParentIdList(parentClassifyIdList []int) (list []*models.Classify, err error) {
+	num := len(parentClassifyIdList)
+	if num <= 0 {
+		return
+	}
+	list, err = models.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 []*models.ClassifyList
+// @param parentId int
+// @return []*models.ClassifyList
+func GetClassifyListTreeRecursive(list []*models.SimpleClassifyList, parentId int) []*models.SimpleClassifyList {
+	res := make([]*models.SimpleClassifyList, 0)
+	for _, v := range list {
+		if v.ParentId == parentId {
+			v.Child = GetClassifyListTreeRecursive(list, v.Id)
+			res = append(res, v)
+		}
+	}
+
+	// 前端的JP需要我这么返回
+	if len(res) <= 0 {
+		res = nil
+	}
+
+	return res
+}
+
+// BySortAndCreateTime 用来排序,先按Sort字段升序排序,若Sort相同,则按照CreateTime字段升序排序。
+type BySortAndCreateTime []*models.SimpleClassifyList
+
+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 []*models.SimpleClassifyList) {
+	sort.Sort(BySortAndCreateTime(classifyList))
+}

+ 34 - 0
services/report.go

@@ -1,8 +1,11 @@
 package services
 
 import (
+	"errors"
 	"fmt"
 	"github.com/PuerkitoBio/goquery"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/utils"
 	"html"
 	"strings"
 )
@@ -31,3 +34,34 @@ func GetReportContentSub(content string) (contentSub string, err error) {
 	})
 	return
 }
+
+// GetMinClassify
+// @Description: 获取最小分类ID
+// @author: Roc
+// @datetime 2024-06-20 09:23:19
+// @param reportInfo *models.Report
+// @return minClassifyId int
+// @return minClassifyName string
+// @return err error
+func GetMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyName string, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error())
+		}
+	}()
+	minClassifyId = reportInfo.ClassifyIdThird
+	minClassifyName = reportInfo.ClassifyNameThird
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdSecond
+		minClassifyName = reportInfo.ClassifyNameSecond
+	}
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdFirst
+		minClassifyName = reportInfo.ClassifyNameFirst
+	}
+	if minClassifyId <= 0 {
+		err = errors.New("分类异常")
+	}
+
+	return
+}

+ 1 - 1
services/report_chapter_type_sync.go

@@ -44,7 +44,7 @@ func EditReportChapterTypeSync(pars *EditReportChapterTypeSyncReq) (err error, e
 }
 
 type EditReportChapterTypeRuleSyncReq struct {
-	ResearchType string `description:"研报类型"`
+	ReportClassifyId int `description:"研报分类id"`
 }
 
 // EditReportChapterTypeRuleSync 同步章节更新设置