xingzai 5 месяцев назад
Родитель
Сommit
53a0a3cf3d

+ 53 - 0
controllers/ficc_report.go

@@ -0,0 +1,53 @@
+package controllers
+
+import (
+	"hongze/hongze_cygx/models"
+	"hongze/hongze_cygx/services"
+)
+
+type FiccYbController struct {
+	BaseAuthController
+}
+
+// @Title 获取报告详情
+// @Description 获取报告详情接口
+// @Param   ReportId   query   int  true       "报告ID"
+// @Success 200 {object} models.ArticleDetailResp
+// @router /detail [get]
+func (this *FiccYbController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+
+	//uid := user.UserId
+	reportId, err := this.GetInt("ReportId")
+	if err != nil {
+		br.Msg = "文章不存在"
+		br.ErrMsg = "文章不存在,文章ID错误" + err.Error()
+		return
+	}
+	if reportId <= 0 {
+		br.Msg = "文章不存在"
+		br.ErrMsg = "文章不存在,文章ID错误"
+		return
+	}
+	detail, err := services.GetReportDetail(user, reportId)
+	if err != nil {
+		br.Msg = "文章不存在"
+		br.ErrMsg = "获取研报信息失败" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = detail
+}

+ 49 - 0
models/ficc_report/classify.go

@@ -0,0 +1,49 @@
+package ficc_report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type Classify struct {
+	Id                   int       `gorm:"column:id" db:"id" json:"id" form:"id"`
+	ClassifyName         string    `gorm:"column:classify_name" db:"classify_name" json:"classify_name" form:"classify_name"` //分类名称
+	Sort                 int8      `gorm:"column:sort" db:"sort" json:"sort" form:"sort"`                                     //排序
+	ParentId             int       `gorm:"column:parent_id" db:"parent_id" json:"parent_id" form:"parent_id"`                 //父级分类id
+	CreateTime           time.Time `gorm:"column:create_time" db:"create_time" json:"create_time" form:"create_time"`
+	ModifyTime           time.Time `gorm:"column:modify_time" db:"modify_time" json:"modify_time" form:"modify_time"`
+	Abstract             string    `gorm:"column:abstract" db:"abstract" json:"abstract" form:"abstract"`                             //栏目简介
+	Descript             string    `gorm:"column:descript" db:"descript" json:"descript" form:"descript"`                             //分享描述
+	ReportAuthor         string    `gorm:"column:report_author" db:"report_author" json:"report_author" form:"report_author"`         //栏目作者
+	AuthorDescript       string    `gorm:"column:author_descript" db:"author_descript" json:"author_descript" form:"author_descript"` //作者简介
+	ReportImgUrl         string    `gorm:"column:report_img_url" db:"report_img_url" json:"report_img_url" form:"report_img_url"`     //报告配图
+	HeadImgUrl           string    `gorm:"column:head_img_url" db:"head_img_url" json:"head_img_url" form:"head_img_url"`             //头部banner
+	AvatarImgUrl         string    `gorm:"column:avatar_img_url" db:"avatar_img_url" json:"avatar_img_url" form:"avatar_img_url"`     //头像
+	ColumnImgUrl         string    `gorm:"column:column_img_url" db:"column_img_url" json:"column_img_url" form:"column_img_url"`     //栏目配图
+	IsHomeColumn         int8      `gorm:"column:is_home_column" db:"is_home_column" json:"is_home_column" form:"is_home_column"`     //1:首页专栏
+	HomeImgUrl           string    `gorm:"column:home_img_url" db:"home_img_url" json:"home_img_url" form:"home_img_url"`             //首页配图
+	ClassifyLabel        string    `gorm:"column:classify_label" db:"classify_label" json:"classify_label" form:"classify_label"`
+	ShowType             uint8     `gorm:"column:show_type" db:"show_type" json:"show_type" form:"show_type"`                                     //展示类型:1-列表 2-专栏
+	HasTeleconference    uint8     `gorm:"column:has_teleconference" db:"has_teleconference" json:"has_teleconference" form:"has_teleconference"` //是否有电话会 0-否 1-是
+	VipTitle             string    `gorm:"column:vip_title" db:"vip_title" json:"vip_title" form:"vip_title"`                                     //研究员头衔
+	YbIconUrl            string    `gorm:"column:yb_icon_url" db:"yb_icon_url" json:"yb_icon_url" form:"yb_icon_url"`                             //研报3.0已购页面icon图片地址
+	YbBgUrl              string    `gorm:"column:yb_bg_url" db:"yb_bg_url" json:"yb_bg_url" form:"yb_bg_url"`                                     //研报3.0已购详情背景图地址
+	IsShow               int8      `gorm:"column:is_show" db:"is_show" json:"is_show" form:"is_show"`                                             //是否展示报告:1,展示该分类下的报告,0隐藏分类下的报告
+	YbFiccIcon           string    `gorm:"column:yb_ficc_icon" db:"yb_ficc_icon" json:"yb_ficc_icon" form:"yb_ficc_icon"`                         //研报小程序端ficc页码图标
+	YbFiccPcIcon         string    `gorm:"column:yb_ficc_pc_icon" db:"yb_ficc_pc_icon" json:"yb_ficc_pc_icon" form:"yb_ficc_pc_icon"`             //研报 pc端ficc页码图标
+	YbFiccSort           int       `gorm:"column:yb_ficc_sort" db:"yb_ficc_sort" json:"yb_ficc_sort" form:"yb_ficc_sort"`                         //研报小程序端ficc页面排序
+	YbListImg            string    `gorm:"column:yb_list_img" db:"yb_list_img" json:"yb_list_img" form:"yb_list_img"`                             //研报小程序端报告列表封面图
+	YbShareBgImg         string    `gorm:"column:yb_share_bg_img;" db:"yb_share_bg_img" json:"yb_share_bg_img" form:"yb_share_bg_img"`
+	YbRightBanner        string    `gorm:"column:yb_right_banner;" db:"yb_right_banner" json:"yb_right_banner" form:"yb_right_banner"`                                // 研报小程序-报告分享背景图
+	Level                int       `gorm:"column:level" db:"level" json:"level" form:"level"`                                                                         // 层级
+	HasChild             int       `gorm:"column:has_child" db:"has_child" json:"has_child" form:"has_child"`                                                         //是否有子级别,0:下面没有子分类,1:下面有子分类;默认:0
+	ReportDetailShowType uint8     `gorm:"column:report_detail_show_type" db:"report_detail_show_type" json:"report_detail_show_type" form:"report_detail_show_type"` // 报告详情的展示类型:1-拼接;2:目录
+}
+
+// GetByClassifyId 根据分类ID查询分类详情
+func GetByClassifyId(id int) (item *Classify, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM classify WHERE id = ? AND is_show = 1 AND enabled = 1 `
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}

+ 20 - 0
models/ficc_report/permission.go

@@ -0,0 +1,20 @@
+package ficc_report
+
+// PermissionCheckInfo 权限校验完成后的结果
+type PermissionCheckInfo struct {
+	Name         string       `json:"name" description:"销售名称"`
+	Mobile       string       `json:"mobile" description:"手机号"`
+	Type         string       `json:"type" description:"校验失败,没有权限,需要让前端处理的类型,枚举值:apply,contact"`
+	HzPhone      string       `json:"hz_phone" description:"弘则公司电话"`
+	CustomerInfo CustomerInfo `json:"customer_info" description:"客户信息"`
+}
+
+// CustomerInfo 客户信息
+type CustomerInfo struct {
+	CompanyName string `json:"company_name" description:"客户(公司)名称"`
+	Name        string `json:"name" description:"联系人名称"`
+	Mobile      string `json:"mobile" description:"手机号"`
+	Status      string `json:"status" description:"状态"`
+	IsSuspend   int8   `json:"is_suspend" description:"启用与否字段:1:暂停,0:启用"`
+	HasApply    bool   `json:"has_apply" description:"是否有申请过"`
+}

+ 129 - 0
models/ficc_report/report.go

@@ -0,0 +1,129 @@
+package ficc_report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ReportDetail struct {
+	ReportInfo           *ReportItem              `json:"report_info"`
+	ReportChapterList    []*ReportChapterListItem `json:"report_chapter_list"`
+	AuthOk               bool                     `json:"auth_ok"`
+	LikeNum              int64                    `description:"点赞总数" json:"like_num"`
+	LikeEnabled          int8                     `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
+	ReportShowType       int                      `description:"展示形式:1-列表 2-专栏" json:"report_show_type"`
+	CollectionId         int                      `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
+	RoadVideoId          int                      `json:"road_video_id" description:"绑定的路演视频ID"`
+	ReportDetailShowType int                      `description:"报告详情的展示类型:1-拼接;2:目录" json:"report_detail_show_type"`
+}
+
+type ReportChapterListItem struct {
+	ReportChapterId        int       `json:"report_chapter_id"`
+	ReportId               int       `json:"report_id"`
+	Title                  string    `json:"title"`
+	TypeId                 int       `json:"type_id"`
+	TypeName               string    `json:"type_name"`
+	Trend                  string    `json:"trend"`
+	ReportChapterTypeKey   string    `json:"report_chapter_type_key"`
+	ReportChapterTypeThumb string    `json:"report_chapter_type_thumb"`
+	ReportChapterTypeName  string    `json:"report_chapter_type_name"`
+	Sort                   int       `json:"sort"`
+	PublishTime            time.Time `json:"publish_time"`
+	IsClose                int       `gorm:"column:is_close;type:tinyint(1);default:0" json:"is_close"` //音频品种是否关闭
+	Content                string    `description:"内容" json:"content"`
+	VideoUrl               string    `json:"video_url" description:"音频文件URL"`
+	VideoName              string    `json:"video_name" description:"音频文件名称"`
+	VideoPlaySeconds       string    `json:"video_play_seconds" description:"音频播放时长"`
+	VideoSize              string    `json:"video_size" description:"音频文件大小,单位M"`
+}
+
+type ReportItem struct {
+	ReportId           int       `json:"report_id"`
+	ClassifyNameFirst  string    `description:"一级分类名称" json:"classify_name_first"`
+	ClassifyNameSecond string    `description:"二级分类名称" json:"classify_name_second"`
+	Title              string    `description:"标题" json:"title"`
+	Abstract           string    `description:"摘要" json:"abstract"`
+	Author             string    `description:"作者" json:"author"`
+	Frequency          string    `description:"频度" json:"frequency"`
+	PublishTime        time.Time `description:"发布时间" json:"publish_time"`
+	Stage              int       `description:"期数" json:"stage"`
+	Content            string    `description:"内容" json:"content"`
+	VideoUrl           string    `description:"音频文件URL" json:"video_url"`
+	VideoName          string    `description:"音频文件名称" json:"video_name"`
+	VideoSize          string    `description:"音频文件大小,单位M" json:"video_size"`
+	VideoPlaySeconds   string    `description:"音频播放时长" json:"video_play_seconds"`
+	VideoImg           string    `description:"音频播放条的图片" json:"video_img"`
+	ContentSub         string    `description:"内容前两个章节" json:"content_sub"`
+	BannerUrl          string    `description:"详情页banner" json:"banner_url"`
+	ShareBgImg         string    `description:"分享背景图" json:"share_bg_img"`
+	HasChapter         int       `description:"是否有章节" json:"has_chapter"`
+	ReportLayout       int8      `description:"报告布局,1:常规布局,2:智能布局。默认:1" json:"report_layout"`
+	HeadImg            string    `description:"报告头图地址" json:"head_img"`
+	EndImg             string    `description:"报告尾图地址" json:"end_img"`
+	CanvasColor        string    `description:"画布颜色" json:"canvas_color"`
+	HeadStyle          string    `description:"版头样式" json:"head_style"`
+	EndStyle           string    `description:"版尾样式" json:"end_style"`
+}
+
+type Report struct {
+	Id                 int       `orm:"column(id)" description:"报告Id"`
+	AddType            int       `json:"-" description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Title              string    `description:"标题"`
+	Abstract           string    `description:"摘要"`
+	Author             string    `description:"作者"`
+	Frequency          string    `description:"频度"`
+	State              int       `description:"状态:1-未提交 2-待审核 3-驳回 4-审核"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `json:"-" description:"消息是否已发送,0:否,1:是"`
+	ThsMsgIsSend       int       `json:"-" description:"客户群消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	VideoSize          string    `description:"音频文件大小,单位M"`
+	ContentSub         string    `json:"-" description:"内容前两个章节"`
+	ReportCode         string    `description:"报告唯一编码"`
+	ReportVersion      int       `json:"-" description:"1:旧版,2:新版"`
+	HasChapter         int       `json:"-" description:"是否有章节 0-否 1-是"`
+	ChapterType        string    `json:"-" description:"章节类型 day-晨报 week-周报"`
+	OldReportId        int       `json:"-" description:"research_report表ID, 大于0则表示该报告为老后台同步过来的"`
+	MsgSendTime        time.Time `json:"-" description:"模版消息发送时间"`
+	AdminId            int       `description:"创建者账号"`
+	AdminRealName      string    `description:"创建者姓名"`
+	ApproveTime        time.Time `description:"审批时间"`
+	PublishTime        time.Time `description:"发布时间"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	// eta1.8.3(研报改版)相关内容
+	ContentStruct       string    `description:"内容组件"`
+	LastModifyAdminId   int       `description:"最后更新人ID"`
+	LastModifyAdminName string    `description:"最后更新人姓名"`
+	ContentModifyTime   time.Time `description:"内容更新时间"`
+	Pv                  int       `description:"pv"`
+	Uv                  int       `description:"uv"`
+	HeadImg             string    `description:"报告头图地址"`
+	EndImg              string    `description:"报告尾图地址"`
+	HeadStyle           string    `description:"版头样式"`
+	EndStyle            string    `description:"版尾样式"`
+	CanvasColor         string    `description:"画布颜色"`
+	NeedSplice          int       `description:"是否拼接版头版位的标记,主要是为了兼容历史报告。0-不需要 1-需要"`
+	HeadResourceId      int       `description:"版头资源ID"`
+	EndResourceId       int       `description:"版尾资源ID"`
+	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:"报告时间创建时间"`
+}
+
+func GetByReportId(reportId int) (item *Report, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report WHERE id =?`
+	err = o.Raw(sql, reportId).QueryRow(&item)
+	return
+}

+ 93 - 0
models/ficc_report/report_chapter.go

@@ -0,0 +1,93 @@
+package ficc_report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_cygx/utils"
+	"time"
+)
+
+type ReportChapter struct {
+	ReportChapterId   int       `gorm:"primaryKey;column:report_chapter_id;type:int(10) unsigned;not null" json:"-"`
+	ReportId          int       `gorm:"column:report_id;type:int(10);not null;default:0"  json:"report_id"`                         //报告ID
+	ReportType        string    `gorm:"column:report_type;type:varchar(255);not null;default:''"  json:"report_type"`               //晨报-day;周报-week;
+	ClassifyIdFirst   int       `gorm:"column:classify_id_first;type:int(10);default:0"  json:"classify_id_first"`                  //一级分类id
+	ClassifyNameFirst string    `gorm:"column:classify_name_first;type:varchar(255);default:''"  json:"classify_name_first"`        //一级分类名称
+	TypeId            int       `gorm:"column:type_id;type:int(10);not null;default:0"  json:"type_id"`                             //品种ID
+	TypeName          string    `gorm:"column:type_name;type:varchar(255);not null;default:''"  json:"type_name"`                   //品种名称
+	Title             string    `gorm:"column:title;type:varchar(255);not null;default:''"  json:"title"`                           //章节标题
+	Abstract          string    `gorm:"column:abstract;type:varchar(255);not null;default:''"  json:"abstract"`                     //摘要
+	AddType           int       `gorm:"column:add_type;type:int(10);not null;default:0"  json:"add_type"`                           //是否为继承报告1-空白报告2-继承报告
+	Author            string    `gorm:"column:author;type:varchar(255);not null;default:''"  json:"author"`                         //作者
+	Content           string    `gorm:"column:content;type:longtext;"  json:"content"`                                              //内容
+	ContentSub        string    `gorm:"column:content_sub;type:longtext;"  json:"content_sub"`                                      //内容前两章
+	Stage             int       `gorm:"column:stage;type:int(10);not null;default:0"  json:"stage"`                                 //期数
+	Trend             string    `gorm:"column:trend;type:varchar(255);not null;default:''"  json:"trend"`                           //趋势观点
+	Sort              int       `gorm:"column:sort;type:int(10);not null;default:0"  json:"sort"`                                   //排序:数值越小越靠前
+	IsEdit            int       `gorm:"column:is_edit;type:int(10);not null;default:0"  json:"is_edit"`                             //是否编辑
+	PublishState      int       `gorm:"column:publish_state;type:int(4);not null;default:0"  json:"publish_state"`                  //发布状态1-待发布2-已发布
+	PublishTime       time.Time `gorm:"column:publish_time;type:datetime"  json:"publish_time"`                                     //发布时间
+	VideoUrl          string    `gorm:"column:video_url;type:varchar(255);not null;default:''"  json:"video_url"`                   //音频文件URL
+	VideoName         string    `gorm:"column:video_name;type:varchar(255);not null;default:''"  json:"video_name"`                 //音频文件名称
+	VideoPlaySeconds  string    `gorm:"column:video_play_seconds;type:varchar(255);not null;default:''"  json:"video_play_seconds"` //音频播放时长
+	VideoSize         string    `gorm:"column:video_size;type:varchar(255);not null;default:''"  json:"video_size"`                 //音频文件大小,单位M
+	CreateTime        time.Time `gorm:"column:create_time;type:datetime"  json:"create_time"`                                       //创建时间
+	ModifyTime        time.Time `gorm:"column:modify_time;type:datetime"  json:"modify_time"`                                       //修改时间
+	ReportLayout      int8      `description:"报告布局,1:常规布局,2:智能布局。默认:1" json:"report_layout"`
+	VoiceGenerateType int8      `description:"音频生成方式,0:系统生成,1:人工上传" json:"voice_generate_type"`
+}
+
+// ReportChapterPermissionMappingItem 报告章节的权限关系表
+type ReportChapterPermissionMappingItem struct {
+	ReportChapterPermissionMappingId int       `gorm:"primaryKey;column:report_chapter_permission_mapping_id" json:"report_chapter_permission_mapping_id"`
+	ReportChapterId                  int       `gorm:"column:report_chapter_id" json:"report_chapter_id"`     // 报告章节的id
+	ChartPermissionId                int       `gorm:"column:chart_permission_id" json:"chart_permission_id"` // 权限id
+	TypeId                           int       `gorm:"column:type_id" json:"type_id"`                         // 报告章节类型id
+	CreateTime                       time.Time `gorm:"column:create_time" json:"create_time"`
+}
+
+// @Description: 根据报告ID列表获取章节
+func GetReportChapterPermissionMappingItemListByReportId(reportId int) (items []*ReportChapterPermissionMappingItem, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.report_chapter_permission_mapping_id ,a.report_chapter_id ,a.chart_permission_id ,a.create_time ,b.type_id
+			FROM  report_chapter_permission_mapping AS a 
+			INNER JOIN report_chapter AS b ON a.report_chapter_id = b.report_chapter_id
+			WHERE b.report_id = ?  `
+	_, err = o.Raw(sql, reportId).QueryRows(&items)
+	return
+}
+
+type ReportChapterList []*ReportChapterListItem
+
+// GetListByChapterIds 根据章节IDs获取列表
+func GetListByChapterIds(chapterIds []int) (items []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	var condition string
+	var pars []interface{}
+	condition = `  AND  publish_state = 2 `
+	if len(chapterIds) > 0 {
+		condition += ` AND report_chapter_id IN (` + utils.GetOrmInReplace(len(chapterIds)) + `) `
+		pars = append(pars, chapterIds)
+	}
+	sql := `SELECT *
+			FROM  report_chapter
+			WHERE 1=1 ` + condition + `   ORDER  BY  sort asc, report_chapter_id asc  `
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetListByReportId 根据报告ID获取章节列表
+func GetListByReportId(reportId int, classifyNameFirst string) (items []*ReportChapter, err error) {
+
+	var where string
+	if classifyNameFirst == "周报" {
+		where = " AND  report_id = ? AND is_edit = 1 AND publish_state = 2"
+	} else {
+		where = " AND  report_id = ? AND publish_state = 2"
+	}
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT report_chapter_id, report_id, type_id, type_name, abstract, title, author, publish_time, trend,video_url,video_name,video_play_seconds,video_size
+			FROM  report_chapter
+			WHERE 1=1 ` + where + `   ORDER  BY  sort asc, report_chapter_id asc  `
+	_, err = o.Raw(sql, reportId).QueryRows(&items)
+	return
+}

+ 38 - 0
models/ficc_report/report_chapter_type.go

@@ -0,0 +1,38 @@
+package ficc_report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ReportChapterType struct {
+	ReportChapterTypeId    uint64    `gorm:"primaryKey;column:report_chapter_type_id;type:bigint(20) unsigned;not null" json:"-"` //研究报告章节id
+	ReportChapterTypeKey   string    `gorm:"column:report_chapter_type_key;type:varchar(32)" json:"report_chapter_type_key"`      //章节key
+	ReportChapterTypeThumb string    `gorm:"column:report_chapter_type_thumb;type:varchar(512)" json:"report_chapter_type_thumb"` //H5展示的图片
+	BannerUrl              string    `gorm:"column:banner_url;type:varchar(512)" json:"banner_url"`                               //banner显示图片
+	ReportChapterTypeName  string    `gorm:"column:report_chapter_type_name;type:varchar(32)" json:"report_chapter_type_name"`    //报告章节类型名称
+	Sort                   int       `gorm:"column:sort;type:int(10);not null;default:0" json:"sort"`                             //排序字段
+	Enabled                int       `gorm:"column:enabled;type:tinyint(1)" json:"enabled"`                                       //报告类型状态
+	CreatedTime            time.Time `gorm:"column:created_time;type:datetime" json:"created_time"`                               //创建时间
+	LastUpdatedTime        time.Time `gorm:"column:last_updated_time;type:datetime" json:"last_updated_time"`                     //更新时间
+	ResearchType           string    `gorm:"column:research_type;type:varchar(30)" json:"research_type"`                          //研报类型
+	SelectedImage          string    `gorm:"column:selected_image;type:varchar(512)" json:"selected_image"`                       //选中时的图片
+	PcSelectedImage        string    `gorm:"column:pc_selected_image;type:varchar(512)" json:"pc_selected_image"`                 //pc选中时的图片
+	UnselectedImage        string    `gorm:"column:unselected_image;type:varchar(512)" json:"unselected_image"`                   //没选中时的图片
+	PcUnselectedImage      string    `gorm:"column:pc_unselected_image;type:varchar(512)" json:"pc_unselected_image"`             //pc没选中时的图片
+	EditImgUrl             string    `gorm:"column:edit_img_url;type:varchar(512)" json:"edit_img_url"`                           //管理后台编辑时选用的图
+	TickerTitle            string    `gorm:"column:ticker_title;type:varchar(128)" json:"ticker_title"`                           //指标列的标题
+	IsShow                 int       `gorm:"column:is_show;type:tinyint(1);default:1" json:"is_show"`                             //是否显示
+	PauseStartTime         time.Time `gorm:"column:pause_start_time;type:datetime" json:"pause_start_time"`                       //暂停开始日期
+	PauseEndTime           time.Time `gorm:"column:pause_end_time;type:datetime" json:"pause_end_time"`                           //暂停结束日期
+	IsSet                  int       `gorm:"column:is_set;type:tinyint(4);default:0" json:"is_set"`
+	YbIconUrl              string    `gorm:"column:yb_icon_url;type:varchar(255) json:"yb_icon_url"`       //研报小程序3.0图标
+	YbBottomIcon           string    `gorm:"column:yb_bottom_icon;type:varchar(255) json:"yb_bottom_icon"` //研报小程序3.0底部菜单图标
+}
+
+func GetEffectTypes() (items []*ReportChapterType, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT *  FROM  report_chapter_type	WHERE is_show=1 AND enabled = 1  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 30 - 0
models/ficc_report/smart_report_resource.go

@@ -0,0 +1,30 @@
+package ficc_report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// SmartReportResource 智能研报-资源表
+type SmartReportResource struct {
+	ResourceID int       `gorm:"primaryKey;column:resource_id" json:"-"`
+	ImgURL     string    `gorm:"column:img_url" json:"imgUrl"`         // 图片链接
+	ImgName    string    `gorm:"column:img_name" json:"imgName"`       // 图片名称
+	Type       int       `gorm:"column:type" json:"type"`              // 类型 1-版头 2-版尾
+	CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 创建时间
+	Style      string    `gorm:"column:style" json:"style"`            // 版图样式
+}
+
+// GetResourceItemById
+// @Description: 根据资源id获取信息
+// @author: Roc
+// @datetime 2024-06-21 16:59:23
+// @param resourceId int
+// @return item *SmartReportResource
+// @return err error
+func GetResourceItemById(resourceId int) (item *SmartReportResource, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM smart_report_resource WHERE resource_id = ?  `
+	err = o.Raw(sql, resourceId).QueryRow(&item)
+	return
+}

+ 18 - 0
routers/commentsRouter.go

@@ -781,6 +781,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:FiccYbController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:FiccYbController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:HomeController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:HomeController"],
         beego.ControllerComments{
             Method: "ListHomeArtAndChart",
@@ -1735,6 +1744,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:YanxuanSpecialController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:YanxuanSpecialController"],
+        beego.ControllerComments{
+            Method: "AddStopTime",
+            Router: `/addStopTimedel`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:YanxuanSpecialController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:YanxuanSpecialController"],
         beego.ControllerComments{
             Method: "AuthorDetail",

+ 5 - 0
routers/router.go

@@ -180,6 +180,11 @@ func init() {
 				&controllers.QuestionnaireController{},
 			),
 		),
+		web.NSNamespace("/ficc_report",
+			web.NSInclude(
+				&controllers.FiccYbController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 379 - 0
services/ficc_report.go

@@ -0,0 +1,379 @@
+package services
+
+//FICC研报
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_cygx/models"
+	"hongze/hongze_cygx/models/ficc_report"
+	"hongze/hongze_cygx/utils"
+	"html"
+)
+
+// 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 *ficc_report.Report) (minClassifyId int, minClassifyName string, err error) {
+	defer func() {
+		if err != nil {
+			go utils.SendAlarmMsg(fmt.Sprint("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error()), 2)
+		}
+
+	}()
+	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
+}
+
+// 获取报告详情
+func GetReportDetail(userinfo *models.WxUserItem, reportId int) (reportDetail ficc_report.ReportDetail, err error) {
+	//var errMsg string
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go utils.SendAlarmMsg(fmt.Sprint("获取研报详情失败 GetFiccYbDetailByApi ,err:", err.Error(), "ReportId:", reportId), 2)
+		}
+	}()
+
+	reportInfo, err := ficc_report.GetByReportId(reportId)
+	if err != nil {
+		//errMsg = err.Error()
+		err = errors.New("报告查询出错")
+		return
+	}
+	if reportInfo.Id == 0 {
+		err = errors.New("报告不存在")
+		return
+	}
+	if reportInfo.State != 2 && reportInfo.State != 6 {
+		err = errors.New("报告未发布")
+		return
+	}
+	// 获取最小分类
+	minClassifyId, _, err := GetMinClassify(reportInfo)
+
+	// 判断报告是否属于专栏报告
+	firstClassify, e := ficc_report.GetByClassifyId(reportInfo.ClassifyIdFirst)
+	if e != nil {
+		err = errors.New("报告一级分类有误")
+		return
+	}
+
+	// 最小分类
+	var minClassify *ficc_report.Classify
+	if reportInfo.ClassifyIdFirst == minClassifyId {
+		minClassify = firstClassify
+	} else {
+		minClassify, e = ficc_report.GetByClassifyId(minClassifyId)
+		if e != nil {
+			err = errors.New("报告最小层级分类有误")
+			return
+		}
+	}
+
+	//判断权限
+
+	var authOk bool
+	var reportChapterIdList []int
+	if reportInfo.HasChapter == 1 {
+		if reportInfo.ClassifyNameFirst == "晨报" {
+			//authOk, permissionCheckInfo, err = CheckDayReportPermission(userinfo, productAuthOk)
+		} else {
+			authOk, _, _, reportChapterIdList, err = CheckWeekReportPermission(userinfo, reportId, true)
+		}
+	}
+
+	authOk = true
+	fmt.Println("reportChapterIdList", reportChapterIdList)
+
+	reportItem := new(ficc_report.ReportItem)
+	reportItem.ReportId = reportInfo.Id
+	reportItem.Title = reportInfo.Title
+	reportItem.PublishTime = reportInfo.PublishTime
+	reportItem.ClassifyNameFirst = reportInfo.ClassifyNameFirst
+	reportItem.ClassifyNameSecond = reportInfo.ClassifyNameSecond
+	reportItem.Stage = reportInfo.Stage
+	reportItem.Abstract = reportInfo.Abstract
+	reportItem.ContentSub = html.UnescapeString(reportInfo.ContentSub)
+	reportItem.Frequency = reportInfo.Frequency
+	reportItem.VideoName = reportInfo.VideoName
+	reportItem.HasChapter = reportInfo.HasChapter
+	reportItem.ReportLayout = reportInfo.ReportLayout
+	reportItem.HeadImg = reportInfo.HeadImg
+	reportItem.EndImg = reportInfo.EndImg
+	reportItem.CanvasColor = reportInfo.CanvasColor
+
+	//版头版尾样式
+	{
+		if reportInfo.HeadResourceId > 0 {
+			headResource, tmpErr := ficc_report.GetResourceItemById(reportInfo.HeadResourceId)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			reportItem.HeadImg = headResource.ImgURL
+			reportItem.HeadStyle = headResource.Style
+		}
+
+		if reportInfo.EndResourceId > 0 {
+			endResource, tmpErr := ficc_report.GetResourceItemById(reportInfo.EndResourceId)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			reportItem.EndImg = endResource.ImgURL
+			reportItem.EndStyle = endResource.Style
+		}
+	}
+
+	if reportInfo.VideoName == "" && reportInfo.VideoUrl != "" {
+		reportItem.VideoName = reportInfo.Title
+	}
+	reportItem.VideoSize = reportInfo.VideoSize
+	reportItem.VideoPlaySeconds = reportInfo.VideoPlaySeconds
+	reportItem.Author = reportInfo.Author
+	// 分享背景图取二级分类配图, 二级没有配图时使用一级配图, 一级也没有使用默认图
+	reportItem.ShareBgImg = utils.DEFAULT_REPORT_SHARE_BG_IMG
+	secondClassify, e := ficc_report.GetByClassifyId(reportInfo.ClassifyIdSecond)
+	if e != nil {
+		err = errors.New("报告二级分类有误")
+		return
+	}
+	if secondClassify.YbShareBgImg != "" {
+		reportItem.ShareBgImg = secondClassify.YbShareBgImg
+	} else {
+		if firstClassify.YbShareBgImg != "" {
+			reportItem.ShareBgImg = firstClassify.YbShareBgImg
+		}
+	}
+	var reportTypeList []*ficc_report.ReportChapterListItem
+
+	if reportInfo.HasChapter == 1 {
+		//(晨报和周报的banner图)
+		if reportInfo.ClassifyNameFirst == "晨报" {
+			reportItem.BannerUrl = utils.ALIYUN_YBIMG_HOST + "report_banner_day.jpg"
+		} else {
+			reportItem.BannerUrl = utils.ALIYUN_YBIMG_HOST + "report_banner_week.jpg"
+		}
+
+		// 如果还没有配置banner图,则取晨报的
+		if reportItem.BannerUrl == `` {
+			reportItem.BannerUrl = utils.ALIYUN_YBIMG_HOST + "report_banner_day.jpg"
+		}
+
+		if authOk {
+			reportTypeList, err = GetChapterListByReportChapterIdList(reportInfo.ClassifyNameFirst, reportInfo.Id, reportChapterIdList)
+			if err != nil {
+				return
+			}
+		}
+	} else {
+		// 音频播放条图片用分类图片
+		//reportItem.VideoImg = utils.HZ_DEFAULT_AVATAR
+		//permissionIds, tmpErr := chart_permission_search_key_word_mapping.GetChartPermissionIdsByKeyWord(reportInfo.ClassifyIdSecond)
+		//if tmpErr != nil {
+		//	errMsg = tmpErr.Error()
+		//	err = errors.New("查询报告权限失败")
+		//	return
+		//}
+		//if len(permissionIds) > 0 {
+		//	chartPermission, tmpErr := chart_permission.GetListByIds(permissionIds)
+		//	if tmpErr != nil {
+		//		errMsg = tmpErr.Error()
+		//		err = errors.New("查询品种信息失败")
+		//		return
+		//	}
+		//	lenChart := len(chartPermission)
+		//	for i := 0; i < lenChart; i++ {
+		//		if chartPermission[i].YbImgUrl != "" {
+		//			reportItem.VideoImg = utils.ALIYUN_YBIMG_HOST + chartPermission[i].YbImgUrl
+		//			break
+		//		}
+		//	}
+		//}
+	}
+	//如果有权限则展示content
+	if authOk {
+		reportItem.Content = html.UnescapeString(reportInfo.Content)
+		reportItem.VideoUrl = reportInfo.VideoUrl
+	}
+
+	reportDetail.ReportInfo = reportItem
+	reportDetail.ReportChapterList = reportTypeList
+	//reportDetail.PermissionCheck = &permissionCheckInfo
+	reportDetail.AuthOk = authOk
+	//reportDetail.LikeNum = likeNum
+	//reportDetail.LikeEnabled = likeEnabled
+	reportDetail.ReportShowType = int(firstClassify.ShowType)
+	reportDetail.ReportDetailShowType = int(minClassify.ReportDetailShowType)
+
+	// 如果分类配置是列表展示,那么就移除content内容
+	if minClassify.ReportDetailShowType == 2 {
+		for _, v := range reportTypeList {
+			v.Content = ``
+		}
+	} else {
+		for _, v := range reportTypeList {
+			v.Content = html.UnescapeString(v.Content)
+		}
+	}
+	return
+}
+
+// CheckWeekReportPermission
+// @Description: 验证周报的权限(并获取拥有权限的章节id列表)
+// @author: Roc
+// @datetime 2024-06-24 11:06:52
+// @param userInfo user.UserInfo
+// @param reportId int
+// @param productAuthOk bool
+// @return authOk bool
+// @return permissionCheckInfo response.PermissionCheckInfo
+// @return validTypeIds []int 分类关联的章节类型ID列表
+// @return reportChapterIdList []int 并获取拥有权限的章节id列表
+// @return err error
+func CheckWeekReportPermission(userInfo *models.WxUserItem, reportId int, productAuthOk bool) (authOk bool, permissionCheckInfo ficc_report.PermissionCheckInfo, validTypeIds, reportChapterIdList []int, err error) {
+	var permissionIds []int
+	//var validPermissionIds []int //最后允许显示的章节
+
+	// 当前报告的品种与章节列表的map
+	permissionChapterList := make(map[int][]int)
+	permissionIdMap := make(map[int]bool)
+	typeIdMap := make(map[int]bool)
+	reportChapterIdMap := make(map[int]bool)
+	if productAuthOk {
+		reportChapterMappingList, e := ficc_report.GetReportChapterPermissionMappingItemListByReportId(reportId)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = errors.New(e.Error())
+			return
+		}
+		for _, v := range reportChapterMappingList {
+			if _, ok := permissionIdMap[v.ChartPermissionId]; !ok {
+				permissionIdMap[v.ChartPermissionId] = true
+				permissionIds = append(permissionIds, v.ChartPermissionId)
+			}
+			if _, ok := typeIdMap[v.TypeId]; !ok {
+				typeIdMap[v.TypeId] = true
+				validTypeIds = append(validTypeIds, v.TypeId)
+			}
+
+			tmpList, ok := permissionChapterList[v.ChartPermissionId]
+			if !ok {
+				tmpList = make([]int, 0)
+			}
+
+			permissionChapterList[v.ChartPermissionId] = append(tmpList, v.ReportChapterId)
+			if _, ok := reportChapterIdMap[v.ReportChapterId]; !ok {
+				reportChapterIdMap[v.ReportChapterId] = true
+				reportChapterIdList = append(reportChapterIdList, v.ReportChapterId) //走权益的校验权限,到这里的权限都可以用
+			}
+		}
+	}
+
+	return
+}
+
+// GetChapterListByReportChapterIdList
+// @Description: 根据报告获取章节列表
+// @author: Roc
+// @datetime 2024-06-24 11:23:36
+// @param classifyNameFirst string
+// @param reportId int
+// @param reportChapterIdList []int
+// @param reportCreateTime time.Time
+// @return reportTypeList response.ReportChapterList
+// @return err error
+func GetChapterListByReportChapterIdList(classifyNameFirst string, reportId int, reportChapterIdList []int) (reportTypeList ficc_report.ReportChapterList, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			go utils.SendAlarmMsg(fmt.Sprintf("GetChapterListByReport: err:%s, errMsg:%s", err.Error(), errMsg), 2)
+		}
+	}()
+	//查询有效的章节
+	typeList, e := ficc_report.GetEffectTypes()
+	if e != nil {
+
+		err = errors.New("章节类型查询出错" + e.Error())
+		return
+	}
+	if len(typeList) == 0 {
+		err = errors.New("无有效的章节")
+		return
+	}
+
+	typeMap := make(map[uint64]*ficc_report.ReportChapterType)
+	for _, v := range typeList {
+		typeMap[v.ReportChapterTypeId] = v
+	}
+
+	var chapterList []*ficc_report.ReportChapter
+	if len(reportChapterIdList) > 0 {
+		//获取所有当前研报有权限的章节
+		chapterList, e = ficc_report.GetListByChapterIds(reportChapterIdList)
+	} else {
+		// 获取所有报告章节
+		chapterList, e = ficc_report.GetListByReportId(reportId, classifyNameFirst)
+	}
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("章节查询出错" + e.Error())
+		return
+	}
+	if len(chapterList) == 0 {
+		err = errors.New("无有效章节")
+		return
+	}
+
+	for _, item := range chapterList {
+		typeItem, ok1 := typeMap[uint64(item.TypeId)]
+		// 如果是配置的章节,那么就需要判断是否禁用,如果禁用,则不展示
+		if item.TypeId > 0 && !ok1 {
+			continue
+		}
+
+		temp := new(ficc_report.ReportChapterListItem)
+		temp.ReportChapterId = item.ReportChapterId
+		temp.TypeId = item.TypeId
+		temp.TypeName = item.TypeName
+		temp.Title = item.Title
+		temp.Trend = item.Trend
+		temp.ReportId = item.ReportId
+		temp.Sort = item.Sort
+		temp.PublishTime = item.PublishTime
+		temp.VideoUrl = item.VideoUrl
+		temp.VideoName = item.VideoName
+		temp.VideoPlaySeconds = item.VideoPlaySeconds
+		temp.VideoSize = item.VideoSize
+		temp.Content = item.Content
+
+		// 系统配置的参数,只有配置的章节类型,才能赋值
+		if typeItem != nil {
+			temp.ReportChapterTypeKey = typeItem.ReportChapterTypeKey
+			temp.ReportChapterTypeName = typeItem.ReportChapterTypeName
+			temp.ReportChapterTypeThumb = typeItem.YbIconUrl
+		}
+
+		reportTypeList = append(reportTypeList, temp)
+	}
+	//if len(reportTypeList) > 0 {
+	//	sort.Sort(reportTypeList)
+	//}
+	return
+}

+ 38 - 0
utils/common.go

@@ -1,8 +1,10 @@
 package utils
 
 import (
+	"crypto/hmac"
 	"crypto/md5"
 	"crypto/sha1"
+	"crypto/sha256"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
@@ -17,6 +19,7 @@ import (
 	"os"
 	"os/exec"
 	"regexp"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -1033,3 +1036,38 @@ func GetMondayAndSundayByTimeString(timeString string) (monday, sunday string) {
 	sunday = sundayDate.Format(FormatDate)
 	return
 }
+
+// HmacSha256 计算HmacSha256
+// key 是加密所使用的key
+// data 是加密的内容
+func HmacSha256(key string, data string) []byte {
+	mac := hmac.New(sha256.New, []byte(key))
+	_, _ = mac.Write([]byte(data))
+
+	return mac.Sum(nil)
+}
+
+// HmacSha256ToBase64 将加密后的二进制转Base64字符串
+func HmacSha256ToBase64(key string, data string) string {
+	return base64.URLEncoding.EncodeToString(HmacSha256(key, data))
+}
+
+func GetSignFiccYbEtaHub(nonce, timestamp string) (sign string) {
+	signStrMap := map[string]string{
+		"nonce":     nonce,
+		"timestamp": timestamp,
+		"appid":     FiccYbEtaHubAppId,
+	}
+	keys := make([]string, 0, len(signStrMap))
+	for k := range signStrMap {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	var signStr string
+	for _, k := range keys {
+		signStr += k + "=" + signStrMap[k] + "&"
+	}
+	signStr = strings.Trim(signStr, "&")
+	sign = HmacSha256ToBase64(FiccYbEtaHubSecret, signStr)
+	return
+}

+ 18 - 0
utils/config.go

@@ -111,6 +111,13 @@ var (
 	SendWxCategoryTemplateMsgUrl string
 )
 
+// FICC 研报
+var (
+	FiccYbEtaHubBusinessCode string //商家编码
+	FiccYbEtaHubAppId        string
+	FiccYbEtaHubSecret       string
+)
+
 func init() {
 	tmpRunMode, err := web.AppConfig.String("run_mode")
 	if err != nil {
@@ -308,6 +315,7 @@ func init() {
 	//易董开放api配置
 	YiDongApiConfig()
 	ChartPermissionId()
+	FiccYbEtaHub()
 }
 
 // YiDongApiConfig 易董开放api配置
@@ -336,6 +344,16 @@ func ChartPermissionId() {
 	}
 }
 
+// 行业ID信息 易董开放api配置
+func FiccYbEtaHub() {
+	if RunMode == "release" {
+		ZHOU_QI_ID = 62
+	} else {
+		FiccYbEtaHubAppId = "IaiJJNFKBXuUgFaG"
+		FiccYbEtaHubSecret = "CJYZocTkUoBZrxaFGzsvFdQCNtqlISqo"
+	}
+}
+
 //
 //YiDongZhengTongYunUrl     string //易董 证通云请求域名
 //YiDongZhengTongYunAppid   string //易董 证通云请求appid

+ 6 - 0
utils/constants.go

@@ -306,3 +306,9 @@ const (
 )
 
 var ACTIVITY_SPECIAL_TRIP_PERMISSION_NAME_OTHER = []string{"策略", "固收", "周期"} //专项调研活动带扣点的行业
+
+// FICC报告
+const (
+	DEFAULT_REPORT_SHARE_BG_IMG = "https://hzstatic.hzinsights.com/static/icon/hzyb/rddp-share-bg.png" // 分享默认背景图
+	ALIYUN_YBIMG_HOST           = "https://hzstatic.hzinsights.com/static/yb_wx/"
+)