浏览代码

fix:新增新版报告分类列表、报告列表、章节列表详情接口

Roc 2 年之前
父节点
当前提交
6db781dc6b

+ 14 - 3
controllers/base_common.go

@@ -15,9 +15,10 @@ type BaseCommon struct {
 }
 
 type Response struct {
-	Code int         `json:"code"`
-	Data interface{} `json:"data"`
-	Msg  string      `json:"msg"`
+	Code   int         `json:"code"`
+	Data   interface{} `json:"data"`
+	Msg    string      `json:"msg"`
+	ErrMsg string      `json:"err_msg"`
 }
 
 const (
@@ -39,6 +40,8 @@ func (c BaseCommon) Result() {
 	}
 	utils.ApiLog.Println("请求地址:", c.Ctx.Input.URI(), "RequestBody:", requestBody, "ResponseBody", string(content), "IP:", ip)
 
+	//不将errMsg暴露给用户
+	c.Response.ErrMsg = c.Response.Msg
 	c.Controller.Data["json"] = c.Response
 	c.Controller.ServeJSON()
 	c.StopRun()
@@ -87,6 +90,14 @@ func (c BaseCommon) FailWithMessage(message string) {
 	c.Result()
 }
 
+func (c BaseCommon) FailWithMessageErr(message, errMsg string) {
+	c.Response.Code = ERROR
+	c.Response.Msg = message
+	c.Response.ErrMsg = errMsg
+	c.Response.Data = map[string]interface{}{}
+	c.Result()
+}
+
 func (c BaseCommon) FailWithDetailed(code int, data interface{}, message string) {
 	c.Response.Code = code
 	c.Response.Msg = message

+ 188 - 0
controllers/report.go

@@ -4,8 +4,11 @@ import (
 	"encoding/json"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/common"
+	"hongze/hongze_open_api/logic"
 	"hongze/hongze_open_api/models/request/article"
+	"hongze/hongze_open_api/models/response/report"
 	celuePushTable "hongze/hongze_open_api/models/tables/article"
+	"hongze/hongze_open_api/models/tables/rddp/classify"
 	tables "hongze/hongze_open_api/models/tables/report"
 	"hongze/hongze_open_api/models/tables/wx_user"
 	"hongze/hongze_open_api/utils"
@@ -25,6 +28,7 @@ type ReportControllerCommon struct {
 	BaseCommon
 }
 
+// ListReport
 // @Title 获取报告列表接口
 // @Description 获取报告列表
 // @Param   _page_size   query   int  true       "每页数据条数"
@@ -139,6 +143,7 @@ func (c *ReportController) ListReport() {
 	c.OkDetailed(resp, "获取成功")
 }
 
+// GetReportInfo
 // @Title 获取报告详情
 // @Description 获取报告详情
 // @Param research_report_id query int true "报告ID"
@@ -208,6 +213,7 @@ func (c *ReportControllerCommon) GetReportInfo() {
 	c.OkDetailed(reportInfo, "获取成功")
 }
 
+// GetResearchReportChapter
 // @Title 获取章节详情接口
 // @Description 获取章节详情
 // @Param ResearchReportTypeId query int true "章节ID"
@@ -261,6 +267,7 @@ func (c *ReportControllerCommon) GetResearchReportChapter() {
 	c.OkDetailed(reportInfo, "获取成功")
 }
 
+// ArticleChange
 // @Title 报告变更通知的插入点接口
 // @Description 报告变更通知的插入点接口
 // @Param	request	body article.CreatArticleCeluePushReq true "type json string"
@@ -302,3 +309,184 @@ func (c *ReportController) ArticleChange() {
 	}
 	c.OkWithMessage("创建成功")
 }
+
+// ClassifyList
+// @Title 获取报告分类列表接口
+// @Description 获取报告分类列表接口
+// @Param   _page_size   query   int  true       "每页数据条数"
+// @Param   _page   query   int  true       "当前页页码,从1开始"
+// @Param   report_type   query   string  true       "类型 day:晨报 、week :周报、two_week:双周报 、month:月报、other :点评 (默认为day:晨报) "
+// @Param   keyword   query   string  true       "搜索关键词"
+// @Param   mobile   query   string  true       "用户手机号(加密后的)"
+// @Success 200 {object} classify.ClassifyList
+// @router /classify/list [get]
+func (c *ReportController) ClassifyList() {
+	list, err := classify.GetClassifyList()
+	if err != nil {
+		c.FailWithMessage("获取分类失败")
+		return
+	}
+	for _, v := range list {
+		childList, err := classify.GetClassifyListByParentId(v.Id)
+		if err != nil {
+			c.FailWithMessage("获取下级分类失败")
+			return
+		}
+		for _, childV := range childList {
+			childV.Child = make([]*classify.ClassifyList, 0)
+		}
+		if len(childList) == 0 {
+			tmpClassifyList := *v
+			tmpClassifyList.Child = make([]*classify.ClassifyList, 0)
+			childList = []*classify.ClassifyList{&tmpClassifyList}
+		}
+		v.Child = childList
+	}
+	c.OkDetailed(list, "获取成功")
+}
+
+// ListReportV2
+// @Title 获取报告列表接口
+// @Description 获取报告列表
+// @Param   _page_size   query   int  true       "每页数据条数"
+// @Param   _page   query   int  true       "当前页页码,从1开始"
+// @Param   classify_id   query   int  true       "分类id"
+// @Param   keyword   query   string  true       "搜索关键词"
+// @Param   mobile   query   string  true       "用户手机号(加密后的)"
+// @Success 200 {object} report.ReportListResp
+// @router /list/v2 [get]
+func (c *ReportController) ListReportV2() {
+	pageSize, _ := c.GetInt("_page_size")
+	currentIndex, _ := c.GetInt("_page")
+	keyword := c.GetString("keyword")
+	classifyId, _ := c.GetInt("classify_id")
+	//mobile := c.GetString("mobile")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	//通过url获取mobile中的参数
+	var mobile string
+	URL, err := url.Parse(c.Ctx.Input.URI())
+	if err != nil {
+		fmt.Println(err)
+		c.FailWithMessage("获取报告失败")
+		return
+	}
+	urlParameter := URL.RawQuery
+	sliceUrl := strings.Split(urlParameter, "&")
+	if len(sliceUrl) > 0 {
+		for _, v := range sliceUrl {
+			if strings.Contains(v, "mobile=") {
+				mobile = strings.Replace(v, "mobile=", "", -1)
+			}
+		}
+	}
+	if mobile == "" {
+		c.FailWithMessage("mobile 必传")
+		return
+	}
+	mobile, err = url.QueryUnescape(mobile)
+	if err != nil {
+		c.FailWithMessage("mobile 必传")
+		return
+	}
+	var dateTxt = []byte(mobile)
+	resultDe := utils.DesBase64Decrypt(dateTxt)
+	deMobile := string(resultDe)
+	if deMobile == "" {
+		c.FailWithMessage("手机号加密格式错误")
+		return
+	}
+	if classifyId <= 0 {
+		c.FailWithMessage("分类必传")
+		return
+	}
+
+	total, list, err, errMsg := logic.GetReportList(classifyId, deMobile, keyword, startSize, pageSize)
+	if err != nil {
+		c.FailWithMessage(errMsg)
+		return
+	}
+
+	page := utils.GetPaging(currentIndex, pageSize, total)
+	resp := report.ReportListResp{
+		List:   list,
+		Paging: page,
+	}
+	c.OkDetailed(resp, "获取成功")
+}
+
+// GetReportInfoV2
+// @Title 获取报告详情
+// @Description 获取报告详情
+// @Param research_report_id query int true "报告ID"
+// @Param   mobile   query   string  true       "用户手机号(加密后的)"
+// @Success 200 {object} report.ResearchReportInfo
+// @router /getReportInfo/v2 [get]
+func (c *ReportControllerCommon) GetReportInfoV2() {
+	reportId, _ := c.GetInt("report_id")
+	//mobile := c.GetString("mobile")
+	if reportId < 1 {
+		c.FailWithMessage("请传入报告id")
+		return
+	}
+	mobile := c.GetString("mobile")
+	if mobile == "" {
+		c.FailWithMessage("mobile 必传")
+		return
+	}
+	var dateTxt = []byte(mobile)
+	resultDe := utils.DesBase64Decrypt(dateTxt)
+	deMobile := string(resultDe)
+	if deMobile == "" {
+		c.FailWithMessage("手机号加密格式错误")
+		return
+	}
+	reportDetail, err, errMsg := logic.GetReportDetail(reportId, deMobile)
+	if err != nil {
+		//c.FailWithMessage(errMsg)
+		c.FailWithMessageErr(errMsg, err.Error())
+		return
+	}
+	c.OkDetailed(reportDetail, "获取成功")
+}
+
+// GetResearchReportChapterV2
+// @Title 获取章节详情接口
+// @Description 获取章节详情
+// @Param ResearchReportTypeId query int true "章节ID"
+// @Param   mobile   query   string  false       "用户手机号(加密后的)"
+// @Success 200 {object} report.ResearchReportTypeContentInfo
+// @router /getReportChapterInfo/v2 [get]
+func (c *ReportControllerCommon) GetResearchReportChapterV2() {
+	reportChapterId, _ := c.GetInt("report_chapter_id")
+	if reportChapterId < 1 {
+		c.FailWithMessage("请传入章节id")
+		return
+	}
+	mobile := c.GetString("mobile")
+	if mobile == "" {
+		c.FailWithMessage("mobile 必传")
+		return
+	}
+	var dateTxt = []byte(mobile)
+	resultDe := utils.DesBase64Decrypt(dateTxt)
+	deMobile := string(resultDe)
+	if deMobile == "" {
+		c.FailWithMessage("手机号加密格式错误")
+		return
+	}
+
+	chapterDetail, err, errMsg := logic.GetChapterDetail(deMobile, reportChapterId)
+	if err != nil {
+		//c.FailWithMessage(errMsg)
+		c.FailWithMessageErr(errMsg, err.Error())
+		return
+	}
+	c.OkDetailed(chapterDetail, "获取成功")
+}

+ 648 - 0
logic/report.go

@@ -0,0 +1,648 @@
+package logic
+
+import (
+	"errors"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/common"
+	reportResp "hongze/hongze_open_api/models/response/report"
+	"hongze/hongze_open_api/models/tables/chart_permission"
+	"hongze/hongze_open_api/models/tables/chart_permission_chapter_mapping"
+	"hongze/hongze_open_api/models/tables/chart_permission_search_key_word_mapping"
+	"hongze/hongze_open_api/models/tables/company_product"
+	"hongze/hongze_open_api/models/tables/company_report_permission"
+	"hongze/hongze_open_api/models/tables/rddp/classify"
+	"hongze/hongze_open_api/models/tables/rddp/report"
+	"hongze/hongze_open_api/models/tables/rddp/report_chapter"
+	"hongze/hongze_open_api/models/tables/report_chapter_type"
+	"hongze/hongze_open_api/models/tables/wx_user"
+	"hongze/hongze_open_api/services/company"
+	"hongze/hongze_open_api/utils"
+	"html"
+	"net/url"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// GetReportList 获取报告列表
+func GetReportList(classifyId int, mobile, keyword string, startSize, pageSize int) (total int, list []*report.ReportList, err error, errMsg string) {
+	//加密后的手机号
+	encryptMobile := string(utils.DesBase64Encrypt([]byte(mobile)))
+	errMsg = `获取失败`
+	// 获取用户信息
+	userInfo, err := wx_user.GetWxUserByMobileCountryCode(mobile, "86")
+	if err != nil {
+		errMsg = "获取用户信息失败"
+		return
+	}
+
+	productId := 1
+	companyProduct, err := company_product.GetCompanyProductByCompanyIdAndProductId(userInfo.CompanyId, productId)
+	if err != nil {
+		errMsg = "获取客户信息失败"
+		return
+	}
+	//`is_suspend` tinyint(4) NOT NULL DEFAULT '0' COMMENT '1:暂停,0:启用',
+	if companyProduct.IsSuspend != 0 {
+		errMsg = "客户状态异常"
+		return
+	}
+
+	permissionList, err := company_report_permission.GetPermissionListByCompanyIdAndProductId(userInfo.CompanyId, productId)
+	if err != nil {
+		errMsg = "获取客户品种失败"
+		return
+	}
+	if len(permissionList) == 0 {
+		errMsg = "客户品种异常"
+		return
+	}
+	//客户品种id列表
+	permissionIdList := make([]int, 0)
+	for _, v := range permissionList {
+		permissionIdList = append(permissionIdList, v.ChartPermissionId)
+	}
+
+	// 获取分类信息
+	classifyInfo, err := classify.GetClassify(classifyId)
+	if err != nil {
+		errMsg = "获取分类信息失败"
+		return
+	}
+	var firstClassifyId, secondClassifyId int
+	firstClassifyId = classifyInfo.ParentId
+	secondClassifyId = classifyInfo.Id
+	if classifyInfo.ParentId <= 0 {
+		firstClassifyId = classifyInfo.Id
+		secondClassifyId = 0
+	}
+
+	var condition string
+	var pars []interface{}
+
+	// 分类
+	condition = ` AND state = 2 AND classify_id_first = ? AND classify_id_second = ? `
+	pars = append(pars, firstClassifyId, secondClassifyId)
+
+	//报告名称
+	if keyword != "" {
+		condition += ` AND  title LIKE ? `
+		pars = append(pars, `%`+keyword+`%`)
+	}
+	total, list, err = report.GetReportList(condition, pars, startSize, pageSize)
+
+	encryptMobile = url.QueryEscape(encryptMobile) //转义 +
+	nonceStr := common.GetRandString(10)
+	timeUnix := strconv.FormatInt(time.Now().Unix(), 10)
+
+	for _, v := range list {
+		if v.Stage > 0 {
+			v.Title = fmt.Sprintf("【第%d期】%s", v.Stage, v.Title)
+		}
+		v.Title = fmt.Sprintf("%s(%s)", v.Title, v.CreateTime.Format(utils.FormatMonthDate))
+
+		//跳转地址
+		postData := make(map[string]string)
+		reportId := strconv.Itoa(v.Id)
+		parameter := "mobile=" + encryptMobile + "&report_id=" + reportId + "&nonce_str=" + nonceStr + "&timestamp=" + timeUnix
+		postData["mobile"] = encryptMobile
+		postData["report_id"] = reportId
+		postData["appid"] = utils.ReportAppid
+		postData["nonce_str"] = nonceStr
+		postData["timestamp"] = timeUnix
+		sign := utils.GetSign(postData)
+		v.HttpUrl = utils.ResearchReportUrl + "hzsl/report/new/detail?" + parameter + "&sign=" + sign
+	}
+	return
+}
+
+// GetReportDetail 获取报告详情
+func GetReportDetail(reportId int, mobile string) (reportDetail reportResp.ReportDetail, err error, errMsg string) {
+	encryptMobile := string(utils.DesBase64Encrypt([]byte(mobile)))
+	errMsg = `获取失败`
+	// 获取用户信息
+	userInfo, err := wx_user.GetWxUserByMobileCountryCode(mobile, "86")
+	if err != nil {
+		errMsg = "获取用户信息失败"
+		return
+	}
+
+	// 判断用户状态是否是正常和永续
+	var productAuthOk bool
+
+	productId := 1
+	companyProduct, err := company_product.GetCompanyProductByCompanyIdAndProductId(userInfo.CompanyId, productId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = nil
+		} else {
+			errMsg = err.Error()
+			err = errors.New("查询用户购买产品出错")
+			return
+		}
+	}
+	if companyProduct != nil {
+		// 无FICC权限的客户不可见
+		if companyProduct.CompanyProductId > 0 {
+			// 已购或者试用用户可见
+			if strings.Contains("永续,正式", companyProduct.Status) || (companyProduct.Status == "试用" && companyProduct.IsSuspend != 1) {
+				productAuthOk = true
+			}
+		}
+	}
+
+	reportInfo, err := report.GetById(reportId)
+	if err != nil {
+		errMsg = "获取报告失败"
+		return
+	}
+	//  `state` tinyint(2) DEFAULT '1' COMMENT '1:未发布,2:已发布',
+	if reportInfo.State != 2 {
+		errMsg = "报告未发布"
+		err = errors.New("报告未发布")
+		return
+	}
+	// 判断报告是否属于专栏报告
+	firstClassify, e := classify.GetClassify(reportInfo.ClassifyIdFirst)
+	if e != nil {
+		errMsg = "报告异常"
+		err = errors.New("报告一级分类有误")
+		return
+	}
+	if firstClassify.IsShow != 1 {
+		errMsg = "报告异常"
+		err = errors.New("报告一级分类未发布")
+		return
+	}
+
+	var authOk bool
+	var permissionCheckInfo reportResp.PermissionCheckInfo
+	var vaildWeekTypeIds []int
+	if reportInfo.ClassifyNameFirst == "晨报" {
+		authOk, permissionCheckInfo, err = CheckDayReportPermission(userInfo, productAuthOk)
+	} else if reportInfo.ClassifyNameFirst == "周报" {
+		authOk, permissionCheckInfo, vaildWeekTypeIds, err = CheckWeekReportPermission(userInfo, productAuthOk)
+	} else {
+		authOk, permissionCheckInfo, err = CheckReportPermission(userInfo, reportId, productAuthOk)
+	}
+	if err != nil {
+		return
+	}
+
+	reportItem := reportResp.ReportItem{
+		ReportId:           reportInfo.Id,
+		ClassifyNameFirst:  reportInfo.ClassifyNameFirst,
+		ClassifyNameSecond: reportInfo.ClassifyNameSecond,
+		Title:              reportInfo.Title,
+		Abstract:           reportInfo.Abstract,
+		Author:             reportInfo.Author,
+		Frequency:          reportInfo.Frequency,
+		PublishTime:        reportInfo.PublishTime,
+		Stage:              reportInfo.Stage,
+		Content:            html.UnescapeString(reportInfo.ContentSub),
+		VideoUrl:           "",
+		VideoName:          reportInfo.VideoName,
+		VideoSize:          reportInfo.VideoSize,
+		VideoPlaySeconds:   reportInfo.VideoPlaySeconds,
+		VideoImg:           "",
+		ContentSub:         "",
+		BannerUrl:          "",
+	}
+
+	if reportInfo.VideoName == "" && reportInfo.VideoUrl != "" {
+		reportItem.VideoName = reportInfo.Title
+	}
+	var reportTypeList []*reportResp.ReportChapterListItem
+
+	if reportInfo.ClassifyNameFirst == "晨报" || reportInfo.ClassifyNameFirst == "周报" {
+		//(晨报和周报的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"
+		}
+		if authOk {
+			reportTypeList, err, errMsg = GetChapterListByReport(reportInfo.ClassifyNameFirst, reportInfo.Id, vaildWeekTypeIds, reportInfo.CreateTime)
+			if err != nil {
+				return
+			}
+		}
+	} else {
+		// 音频播放条图片用分类图片
+		reportItem.VideoImg = utils.HZ_DEFAULT_AVATAR
+		permissionIds, tmpErr := chart_permission_search_key_word_mapping.GetChartPermissionIdsByKeyWord(reportItem.ClassifyNameSecond)
+		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
+	//var likeNum int64
+	//var likeEnabled int8
+	if authOk {
+		//go AddViewRecord(userinfo, reportInfo.Id, reportInfo.ClassifyNameFirst, 0)
+		reportItem.Content = html.UnescapeString(reportInfo.Content)
+		reportItem.VideoUrl = reportInfo.VideoUrl
+		//查询点赞数
+		//likeNum,likeEnabled, _ = services.GetReportLikeByReportIdOldReportId(userinfo.UserID, reportInfo.Id, 0,0,0)
+	}
+
+	encryptMobile = url.QueryEscape(encryptMobile) //转义 +
+	nonceStr := common.GetRandString(10)
+	timeUnix := strconv.FormatInt(time.Now().Unix(), 10)
+
+	for _, v := range reportTypeList {
+		//跳转地址
+		postData := make(map[string]string)
+		reportChapterId := strconv.Itoa(v.ReportChapterId)
+		parameter := "mobile=" + encryptMobile + "&report_chapter_id=" + reportChapterId + "&nonce_str=" + nonceStr + "&timestamp=" + timeUnix
+		postData["mobile"] = encryptMobile
+		postData["report_chapter_id"] = reportChapterId
+		postData["appid"] = utils.ReportAppid
+		postData["nonce_str"] = nonceStr
+		postData["timestamp"] = timeUnix
+		sign := utils.GetSign(postData)
+		v.HttpUrl = utils.ResearchReportUrl + "hzsl/report/new/chapter/detail?" + parameter + "&sign=" + sign
+	}
+
+	reportDetail.ReportInfo = reportItem
+	reportDetail.ReportChapterList = reportTypeList
+	reportDetail.PermissionCheck = permissionCheckInfo
+	reportDetail.AuthOk = authOk
+	//reportDetail.LikeNum = likeNum
+	//reportDetail.LikeEnabled = likeEnabled
+	reportDetail.ReportShowType = firstClassify.ShowType
+	return
+}
+
+// GetChapterListByReport 根据报告获取章节列表
+func GetChapterListByReport(classifyNameFirst string, reportId int, validWeekTypeIds []int, reportCreateTime time.Time) (reportTypeList reportResp.ReportChapterList, err error, errMsg string) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Critical(fmt.Sprintf("GetChapterListByReport: err:%s, errMsg:%s", err.Error(), errMsg))
+		}
+	}()
+
+	//查询有效的章节
+	typeList, err := report_chapter_type.GetEffectTypes()
+	if err != nil {
+		errMsg = "章节类型查询出错"
+		return
+	}
+	if len(typeList) == 0 {
+		errMsg = "无有效的章节"
+		err = errors.New("无有效的章节")
+		return
+	}
+
+	typeMap := make(map[uint64]*report_chapter_type.ReportChapterType)
+	var typeIds []int
+	newTypeMap := make(map[int]bool)
+	for _, v := range typeList {
+		typeMap[v.ReportChapterTypeId] = v
+		typeIds = append(typeIds, int(v.ReportChapterTypeId))
+	}
+
+	if classifyNameFirst == "周报" {
+		for _, v := range validWeekTypeIds {
+			newTypeMap[v] = true
+		}
+	}
+	//获取所有当前研报的章节
+	chapterList, err := report_chapter.GetListByReportId(reportId, classifyNameFirst)
+	if err != nil {
+		errMsg = "章节查询出错"
+		return
+	}
+	if len(chapterList) == 0 {
+		errMsg = "无有效章节"
+		err = errors.New("无有效章节")
+		return
+	}
+
+	for _, item := range chapterList {
+		if typeItem, ok := typeMap[uint64(item.TypeId)]; ok {
+			// 如果是周报只展示有权限的章节
+			if classifyNameFirst == "周报" {
+				if _, ok1 := newTypeMap[item.TypeId]; !ok1 {
+					continue
+				}
+			}
+			temp := new(reportResp.ReportChapterListItem)
+			if reportCreateTime.Before(typeItem.PauseStartTime) || reportCreateTime.After(typeItem.PauseEndTime) {
+				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 = typeItem.Sort
+				temp.PublishTime = item.PublishTime
+				temp.ReportChapterTypeKey = typeItem.ReportChapterTypeKey
+				temp.ReportChapterTypeName = typeItem.ReportChapterTypeName
+				temp.ReportChapterTypeThumb = typeItem.YbIconUrl
+				reportTypeList = append(reportTypeList, temp)
+			}
+		}
+	}
+	if len(reportTypeList) > 0 {
+		sort.Sort(reportTypeList)
+	}
+	return
+}
+
+// GetChapterDetail 获取章节详情
+func GetChapterDetail(mobile string, reportChapterId int) (reportChapterDetail reportResp.ReportChapterDetail, err error, errMsg string) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Critical(fmt.Sprintf("GetChapterDetail: mobile=%s, err:%s, errMsg:%s", mobile, err.Error(), errMsg))
+		}
+	}()
+	encryptMobile := string(utils.DesBase64Encrypt([]byte(mobile)))
+	errMsg = `获取失败`
+	// 获取用户信息
+	userInfo, err := wx_user.GetWxUserByMobileCountryCode(mobile, "86")
+	if err != nil {
+		errMsg = "获取用户信息失败"
+		return
+	}
+	var authOk bool
+	var productAuthOk bool
+	var chapterAuthOk bool
+	var permissionCheckInfo reportResp.PermissionCheckInfo
+
+	//查询客户信息(判断客户状态是否是正常和永续)
+	productId := 1
+	companyProduct, err := company_product.GetCompanyProductByCompanyIdAndProductId(userInfo.CompanyId, productId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = nil
+		} else {
+			errMsg = err.Error()
+			err = errors.New("查询用户购买产品出错")
+			return
+		}
+	}
+	if companyProduct != nil {
+		// 无FICC权限的客户不可见
+		if companyProduct.CompanyProductId > 0 {
+			// 已购或者试用用户可见
+			if strings.Contains("永续,正式", companyProduct.Status) || (companyProduct.Status == "试用" && companyProduct.IsSuspend != 1) {
+				productAuthOk = true
+			}
+		}
+	}
+
+	//章节分类
+	typeIds, err := report_chapter_type.GetEffectTypeID()
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("章节类型查询出错")
+		return
+	}
+	if len(typeIds) == 0 {
+		err = errors.New("无有效的章节类型")
+		return
+	}
+	reportChapter, err := report_chapter.GetContentById(reportChapterId, typeIds)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("章节查询出错")
+		return
+	}
+
+	if reportChapter.ReportChapterId == 0 {
+		err = errors.New("章节不存在")
+		return
+	}
+
+	//报告信息
+	reportInfo, tErr := report.GetById(reportChapter.ReportId)
+	if tErr != nil {
+		errMsg = tErr.Error()
+		err = errors.New("报告查询出错")
+		return
+	}
+	if reportInfo.Id == 0 {
+		err = errors.New("报告不存在")
+		return
+	}
+	if reportInfo.ClassifyNameFirst == "周报" && reportChapter.IsEdit != 1 {
+		err = errors.New("章节未编辑")
+		return
+	}
+
+	//判断权限
+	var reportChapterTypeIds []int
+	if reportInfo.ClassifyNameFirst == "晨报" {
+		authOk, permissionCheckInfo, err = CheckDayReportPermission(userInfo, productAuthOk)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			errMsg = err.Error()
+			err = errors.New("权限查询出错")
+			return
+		}
+	} else if reportInfo.ClassifyNameFirst == "周报" {
+		authOk, permissionCheckInfo, reportChapterTypeIds, err = CheckWeekReportPermission(userInfo, productAuthOk)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			errMsg = err.Error()
+			err = errors.New("权限查询出错")
+			return
+		}
+		for _, v := range reportChapterTypeIds {
+			if v == reportChapter.TypeId {
+				chapterAuthOk = true
+			}
+		}
+		authOk = chapterAuthOk
+	}
+
+	videoImgMap := map[string]string{
+		"day":  "report_list_chen.png",
+		"week": "report_list_zhou.png",
+	}
+
+	reportChapterItem := reportResp.ReportChapterItem{
+		ReportChapterId:       reportChapter.ReportChapterId,
+		ReportId:              reportChapter.ReportId,
+		Title:                 reportChapter.Title,
+		Abstract:              reportChapter.Abstract,
+		TypeId:                reportChapter.TypeId,
+		TypeName:              reportChapter.TypeName,
+		Trend:                 "",
+		ReportChapterTypeName: "",
+		PublishTime:           reportChapter.PublishTime,
+		Content:               "",
+		ContentSub:            html.UnescapeString(reportChapter.ContentSub),
+		VideoUrl:              "",
+		VideoName:             reportChapter.VideoName,
+		VideoPlaySeconds:      reportChapter.VideoPlaySeconds,
+		VideoSize:             reportChapter.VideoSize,
+		VideoImg:              utils.ALIYUN_YBIMG_HOST + videoImgMap[reportChapter.ReportType],
+		Author:                reportChapter.Author,
+		Stage:                 reportChapter.Stage,
+		ClassifyIdFirst:       reportChapter.ClassifyIdFirst,
+		ClassifyNameFirst:     reportChapter.ClassifyNameFirst,
+	}
+	if reportChapter.VideoUrl != "" && reportChapter.VideoName == "" {
+		reportChapterItem.VideoName = reportChapter.Title
+	}
+
+	//var likeNum int64
+	//var likeEnabled int8
+	//底部菜单切换
+	var chapterMenu []reportResp.ReportChapterMenu
+	if authOk {
+		reportChapterItem.Content = html.UnescapeString(reportChapter.Content)
+		reportChapterItem.VideoUrl = reportChapter.VideoUrl
+		//底部菜单切换
+		if reportInfo.ClassifyNameFirst == "周报" {
+			chapterMenu, err = GetMenuChapter(reportInfo.Id, reportChapterTypeIds, reportInfo.ClassifyNameFirst, reportInfo.CreateTime, encryptMobile)
+		} else {
+			chapterMenu, err = GetMenuChapter(reportInfo.Id, typeIds, reportInfo.ClassifyNameFirst, reportInfo.CreateTime, encryptMobile)
+		}
+		//查询点赞数
+		//likeNum,likeEnabled, _ = services.GetReportLikeByReportIdOldReportId(user.UserID, reportInfo.Id, reportChapter.ReportChapterId,0,0)
+		//go AddViewRecord(user, reportInfo.Id, reportInfo.ClassifyNameFirst, reportChapterId)
+	} else {
+		reportChapterItem.ContentSub = html.UnescapeString(reportChapter.ContentSub)
+	}
+
+	reportChapterDetail = reportResp.ReportChapterDetail{
+		ReportChapterItem:     reportChapterItem,
+		ReportChapterMenuList: chapterMenu,
+		AuthOk:                authOk,
+		PermissionCheck:       permissionCheckInfo,
+		//LikeNum:               0,
+		//LikeEnabled:           0,
+	}
+	//reportChapterDetail.PermissionCheck = &permissionCheckInfo
+	//reportChapterDetail.LikeNum = likeNum
+	//reportChapterDetail.LikeEnabled = likeEnabled
+	return
+}
+
+// GetMenuChapter 获取章节下面的菜单
+func GetMenuChapter(reportId int, typeIds []int, classifyNameFirst string, reportCreateTime time.Time, encryptMobile string) (reportTypeList reportResp.ReportChapterMenuList, err error) {
+	//查询有效的章节
+	typeList, tErr := report_chapter_type.GetEffectTypes()
+	if tErr != nil {
+		return
+	}
+	if len(typeList) == 0 {
+		err = errors.New("无有效的章节")
+		return
+	}
+
+	typeMap := make(map[uint64]*report_chapter_type.ReportChapterType)
+	for _, v := range typeList {
+		typeMap[v.ReportChapterTypeId] = v
+	}
+
+	//获取所有当前研报的章节
+	chapterList, tErr := report_chapter.GetListByReportIdTypeIds(reportId, typeIds, classifyNameFirst)
+	if tErr != nil {
+		return
+	}
+
+	encryptMobile = url.QueryEscape(encryptMobile) //转义 +
+	nonceStr := common.GetRandString(10)
+	timeUnix := strconv.FormatInt(time.Now().Unix(), 10)
+	if len(chapterList) > 0 {
+		for _, item := range chapterList {
+			if typeItem, ok := typeMap[uint64(item.TypeId)]; ok {
+				if reportCreateTime.Before(typeItem.PauseStartTime) || reportCreateTime.After(typeItem.PauseEndTime) {
+					//typeItem.ReportChapterTypeId
+					//跳转地址
+					postData := make(map[string]string)
+					reportChapterId := strconv.Itoa(item.ReportChapterId)
+					parameter := "mobile=" + encryptMobile + "&report_chapter_id=" + reportChapterId + "&nonce_str=" + nonceStr + "&timestamp=" + timeUnix
+					postData["mobile"] = encryptMobile
+					postData["report_chapter_id"] = reportChapterId
+					postData["appid"] = utils.ReportAppid
+					postData["nonce_str"] = nonceStr
+					postData["timestamp"] = timeUnix
+					sign := utils.GetSign(postData)
+
+					temp := reportResp.ReportChapterMenu{
+						ReportChapterId:        item.ReportChapterId,
+						ReportId:               item.ReportId,
+						ReportChapterTypeName:  typeItem.ReportChapterTypeName,
+						ReportChapterTypeThumb: typeItem.YbBottomIcon,
+						PcSelectedThumb:        typeItem.PcSelectedImage,
+						PcUnselectedThumb:      typeItem.PcUnselectedImage,
+						Sort:                   typeItem.Sort,
+						HttpUrl:                utils.ResearchReportUrl + "hzsl/report/new/chapter/detail?" + parameter + "&sign=" + sign,
+					}
+
+					reportTypeList = append(reportTypeList, temp)
+				}
+			}
+		}
+	}
+	if len(reportTypeList) > 0 {
+		sort.Sort(reportTypeList)
+	}
+	return
+}
+
+// CheckDayReportPermission 验证晨报的权限
+func CheckDayReportPermission(userInfo *wx_user.WxUser, productAuthOk bool) (authOk bool, permissionCheckInfo reportResp.PermissionCheckInfo, err error) {
+	if productAuthOk {
+		authOk = true
+		return
+	}
+	authOk, permissionCheckInfo, _, err = company.GetCheckPermission(userInfo.CompanyId, int(userInfo.UserId), []int{})
+	return
+}
+
+// CheckWeekReportPermission 验证周报的权限
+func CheckWeekReportPermission(userInfo *wx_user.WxUser, productAuthOk bool) (authOk bool, permissionCheckInfo reportResp.PermissionCheckInfo, validTypeIds []int, err error) {
+	var permissionIds []int
+	var validPermissionIds []int //最后允许显示的章节
+	if productAuthOk {
+		permissionIds, err = chart_permission_chapter_mapping.GetPermissionIdsByWeek()
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			return
+		}
+	}
+	authOk, permissionCheckInfo, validPermissionIds, err = company.GetCheckPermission(userInfo.CompanyId, int(userInfo.UserId), permissionIds)
+	if err != nil {
+		return
+	}
+	//返回可用的章节列表
+	if len(validPermissionIds) > 0 {
+		validTypeIds, err = chart_permission_chapter_mapping.GetReportChapterTypeIdsByPermissionIds(validPermissionIds, "week")
+	}
+	return
+}
+
+// CheckReportPermission 验证用户查看报告的权限
+func CheckReportPermission(userInfo *wx_user.WxUser, reportId int, productAuthOk bool) (authOk bool, permissionCheckInfo reportResp.PermissionCheckInfo, err error) {
+	var permissionIds []int
+	if productAuthOk {
+		permissionIds, err = chart_permission_chapter_mapping.GetPermissionIdsByReportId(reportId, "rddp")
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			return
+		}
+	}
+	authOk, permissionCheckInfo, _, err = company.GetCheckPermission(userInfo.CompanyId, int(userInfo.UserId), permissionIds)
+	return
+}

+ 160 - 0
models/response/report/report.go

@@ -0,0 +1,160 @@
+package report
+
+import (
+	"hongze/hongze_open_api/models/tables/rddp/classify"
+	"hongze/hongze_open_api/models/tables/rddp/report"
+	"hongze/hongze_open_api/utils"
+	"time"
+)
+
+// 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   int    `json:"is_suspend" description:"启用与否字段:1:暂停,0:启用"`
+	HasApply    bool   `json:"has_apply" description:"是否有申请过"`
+}
+
+// ReportClassifyListResp 分类列表接口
+type ReportClassifyListResp struct {
+	List []*classify.ClassifyList `description:"列表"  json:"list"`
+}
+
+// ReportListResp 报告列表接口
+type ReportListResp struct {
+	List   []*report.ReportList `description:"列表"  json:"list"`
+	Paging *utils.PagingItem    `description:"分页数据" json:"paging"`
+}
+
+type ReportChapterList []*ReportChapterListItem
+
+func (r ReportChapterList) Len() int {
+	return len(r)
+}
+
+func (r ReportChapterList) Less(i, j int) bool {
+	return r[i].Sort < r[j].Sort
+}
+
+func (r ReportChapterList) Swap(i, j int) {
+	r[i], r[j] = r[j], r[i]
+}
+
+// ReportDetail 报告详情
+type ReportDetail struct {
+	ReportInfo        ReportItem               `json:"report_info"`
+	ReportChapterList []*ReportChapterListItem `json:"report_chapter_list"`
+	PermissionCheck   PermissionCheckInfo      `json:"permission_check"`
+	AuthOk            bool                     `json:"auth_ok"`
+	LikeNum           int64                    `description:"点赞总数" json:"-"`
+	LikeEnabled       int8                     `description:"是否已点赞: 0-未点赞 1-已点赞" json:"-"`
+	ReportShowType    int                      `descritpion:"展示形式:1-列表 2-专栏" json:"report_show_type"`
+}
+
+// ReportItem 报告详情返回数据
+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"`
+}
+
+// ReportChapterListItem 报告详情章节返回结构体
+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"`
+	HttpUrl                string    `json:"http_url"`
+}
+
+// ReportChapterDetail 报告章节详情
+type ReportChapterDetail struct {
+	ReportChapterItem     ReportChapterItem   `json:"report_chapter_item"`
+	PermissionCheck       PermissionCheckInfo `json:"permission_check"`
+	ReportChapterMenuList []ReportChapterMenu `json:"report_chapter_menu_list"`
+	AuthOk                bool                `json:"auth_ok"`
+	LikeNum               int64               `description:"点赞总数" json:"like_num"`
+	LikeEnabled           int8                `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
+}
+
+// ReportChapterMenu 报告章节里面的菜单
+type ReportChapterMenu struct {
+	ReportChapterId        int    `json:"report_chapter_id"`
+	ReportId               int    `json:"report_id"`
+	ReportChapterTypeName  string `json:"report_chapter_type_name"`
+	ReportChapterTypeThumb string `json:"report_chapter_type_thumb"`
+	PcSelectedThumb        string `json:"pc_selected_thumb"`
+	PcUnselectedThumb      string `json:"pc_unselected_thumb"`
+	Sort                   int    `json:"sort"`
+	HttpUrl                string `json:"http_url"`
+}
+
+// ReportChapterItem 报告章节详情
+type ReportChapterItem struct {
+	ReportChapterId       int       `json:"report_chapter_id"`
+	ReportId              int       `json:"report_id"`
+	Title                 string    `json:"title"`
+	Abstract              string    `json:"abstract"`
+	TypeId                int       `json:"type_id"`
+	TypeName              string    `json:"type_name"`
+	Trend                 string    `json:"trend"`
+	ReportChapterTypeName string    `json:"report_chapter_type_name"`
+	PublishTime           time.Time `json:"publish_time"`
+	Content               string    `description:"内容" json:"content"`
+	ContentSub            string    `description:"内容前两个章节" json:"content_sub"`
+	VideoUrl              string    `json:"video_url"`          //音频文件URL
+	VideoName             string    `json:"video_name"`         //音频文件名称
+	VideoPlaySeconds      string    `json:"video_play_seconds"` //音频播放时长
+	VideoSize             string    `json:"video_size"`
+	VideoImg              string    `description:"音频播放条的图片" json:"video_img"`
+	Author                string    `description:"作者" json:"author"`
+	Stage                 int       `description:"期数" json:"stage"`
+	ClassifyIdFirst       int       `description:"一级分类id" json:"classify_id_first"`
+	ClassifyNameFirst     string    `description:"一级分类名称" json:"classify_name_first"`
+}
+
+type ReportChapterMenuList []ReportChapterMenu
+
+func (rc ReportChapterMenuList) Len() int {
+	return len(rc)
+}
+
+func (rc ReportChapterMenuList) Less(i, j int) bool {
+	return rc[i].Sort < rc[j].Sort
+}
+
+func (rc ReportChapterMenuList) Swap(i, j int) {
+	rc[i], rc[j] = rc[j], rc[i]
+}

+ 8 - 0
models/tables/admin/admin.go

@@ -44,3 +44,11 @@ func GetSysAdminCountByMobile(mobile string) (count int, err error) {
 	err = o.Raw(sql, mobile).QueryRow(&count)
 	return
 }
+
+// GetByAdminId 查询系统中是否存在该手机号(如果有传入用户id,那么排除该用户)
+func GetByAdminId(adminId int) (item *Admin, err error) {
+	sql := `SELECT * FROM admin WHERE admin_id=? `
+	o := orm.NewOrm()
+	err = o.Raw(sql, adminId).QueryRow(&item)
+	return
+}

+ 42 - 0
models/tables/chart_permission/chart_permission.go

@@ -0,0 +1,42 @@
+package chart_permission
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_open_api/utils"
+	"time"
+)
+
+// ChartPermission 报告权限表
+type ChartPermission struct {
+	ChartPermissionId   int       `orm:"column(chart_permission_id);pk" description:"问题ID"`
+	ChartPermissionName string    `description:"名称"`
+	PermissionName      string    `description:"权限名"`
+	Sort                int       `description:"排序"`
+	Enabled             int       `description:"是否可用"`
+	CreatedTime         time.Time `description:"创建时间"`
+	LastUpdatedTime     time.Time `description:"更新时间"`
+	TeleconferenceSort  int       `description:"电话会类型排序"`
+	Remark              string    `description:"备注"`
+	ClassifyName        string    `description:"分类名称"`
+	ProductName         string    `description:"产品名称"`
+	ProductID           int       `description:"产品ID"`
+	ImageURL            string    `description:"图片地址"`
+	ShowType            int       `description:"1:查研观向小程序展示"`
+	IsOther             int       `description:"是否是其他,用于查研观向小程序后台展示"`
+	IsReport            int       `description:"是否是报告,用于查研观向小程序前台报告展示"`
+	CygxAuth            int       `description:"是否是权限,用于查研观向小程序前台权限校验"`
+	YbImgUrl            string    `description:"研报小程序报告列表icon"`
+	PriceDrivenState    int       `description:"品种价格驱动开启状态 0-关闭 1-开启"`
+}
+
+// GetListByIds 通过IDs获取图表权限集合
+func GetListByIds(permissionIds []int) (list []*ChartPermission, err error) {
+	lenNum := len(permissionIds)
+	if lenNum == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := "SELECT * from chart_permission_chapter_mapping WHERE chart_permission_id in (" + utils.GetOrmInReplace(lenNum) + ") "
+	_, err = o.Raw(sql, permissionIds).QueryRows(&list)
+	return
+}

+ 73 - 0
models/tables/chart_permission_chapter_mapping/chart_permission_chapter_mapping.go

@@ -0,0 +1,73 @@
+package chart_permission_chapter_mapping
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_open_api/utils"
+)
+
+type ChartPermissionChapterMapping struct {
+	Id                  int    `orm:"column(id);pk"`
+	ChartPermissionId   int    `description:"权限ID"`
+	ReportChapterTypeId int    `description:"report_chapter_type表主键id或research_report表主键id或tactic表主键id"`
+	ResearchType        string `description:"报告类型 week;two_week;tactic;month;other;rddp; "`
+}
+
+// GetReportChapterTypeIdsByPermissionIds 根据权限ID筛选报告分类ID, rddp 类型表示新后台新增的报告,区分老后台
+func GetReportChapterTypeIdsByPermissionIds(permissionIds []int, researchType string) (reportIds []int, err error) {
+	lenNum := len(permissionIds)
+	if lenNum < 0 {
+		return
+	}
+	var charPermissionMapping []*ChartPermissionChapterMapping
+	o := orm.NewOrm()
+	sql := "SELECT DISTINCT report_chapter_type_id from chart_permission_chapter_mapping WHERE chart_permission_id in (" + utils.GetOrmInReplace(lenNum) + ") and research_type = ?"
+	_, err = o.Raw(sql, permissionIds, researchType).QueryRows(&charPermissionMapping)
+	if err != nil {
+		return
+	}
+	for _, v := range charPermissionMapping {
+		reportIds = append(reportIds, v.ReportChapterTypeId)
+	}
+	return
+}
+
+// GetPermissionIdsByReportId 根据报告获取品种权限id
+func GetPermissionIdsByReportId(reportId int, researchType string) (ids []int, err error) {
+	o := orm.NewOrm()
+	var list []*ChartPermissionChapterMapping
+
+	sql := "SELECT DISTINCT chart_permission_id from chart_permission_chapter_mapping WHERE report_chapter_type_id = ? and research_type = ?"
+	_, err = o.Raw(sql, reportId, researchType).QueryRows(&list)
+	if err != nil {
+		return
+	}
+
+	fmt.Println(list)
+	if len(list) > 0 {
+		for _, item := range list {
+			ids = append(ids, item.ChartPermissionId)
+		}
+	}
+	return
+}
+
+// GetPermissionIdsByWeek 根据周度报告获取品种权限id
+func GetPermissionIdsByWeek() (ids []int, err error) {
+	o := orm.NewOrm()
+	var list []*ChartPermissionChapterMapping
+
+	sql := `SELECT DISTINCT chart_permission_id from chart_permission_chapter_mapping WHERE  research_type = "week" `
+	_, err = o.Raw(sql).QueryRows(&list)
+	if err != nil {
+		return
+	}
+
+	fmt.Println(list)
+	if len(list) > 0 {
+		for _, item := range list {
+			ids = append(ids, item.ChartPermissionId)
+		}
+	}
+	return
+}

+ 32 - 0
models/tables/chart_permission_search_key_word_mapping/chart_permission_search_key_word_mapping.go

@@ -0,0 +1,32 @@
+package chart_permission_search_key_word_mapping
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ChartPermissionSearchKeyWordMapping struct {
+	Id                 int    `orm:"column(id);pk" json:"id"`
+	ChartPermissionId  int    `json:"chart_permission_id"`
+	KeyWord            string `json:"key_word"`
+	From               string `json:"from"`
+	TacticType         string `json:"tactic_type"`
+	TeleconferenceSort int    ` json:"teleconference_sort"`
+}
+
+// GetChartPermissionIdsByKeyWord 查询二级分类中的权限
+func GetChartPermissionIdsByKeyWord(keyWord string) (ids []int, err error) {
+	o := orm.NewOrm()
+	var list []*ChartPermissionSearchKeyWordMapping
+	sql := "SELECT * from chart_permission_search_key_word_mapping WHERE key_word = ? and `from` = 'rddp'"
+	_, err = o.Raw(sql, keyWord).QueryRows(&list)
+	if err != nil {
+		return
+	}
+
+	if len(list) > 0 {
+		for _, item := range list {
+			ids = append(ids, item.ChartPermissionId)
+		}
+	}
+	return
+}

+ 23 - 49
models/tables/company_report_permission/company_report_permission.go

@@ -1,56 +1,30 @@
 package company_report_permission
 
-import "time"
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
 
-// CompanyReportPermission 客户权限表
 type CompanyReportPermission struct {
-	CompanyReportPermissionID uint64    `gorm:"primaryKey;column:company_report_permission_id;type:bigint(20) unsigned;not null" json:"-"`         // 主键
-	CompanyID                 int64     `gorm:"uniqueIndex:uni_key;column:company_id;type:bigint(20);default:0" json:"companyId"`                  // 客户id
-	ReportPermissionID        int64     `gorm:"column:report_permission_id;type:bigint(20)" json:"reportPermissionId"`                             // 报告权限id
-	CreatedTime               time.Time `gorm:"index:created_time;column:created_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createdTime"` // 创建时间
-	LastUpdatedTime           time.Time `gorm:"index:last_updated_time;column:last_updated_time;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"lastUpdatedTime"`
-	ChartPermissionID         int       `gorm:"uniqueIndex:uni_key;column:chart_permission_id;type:int(11);default:0" json:"chartPermissionId"` // 大分类ID
-	StartDate                 time.Time `gorm:"column:start_date;type:date" json:"startDate"`                                                   // 权限开始日期
-	EndDate                   time.Time `gorm:"column:end_date;type:date" json:"endDate"`                                                       // 权限结束日期
-	ProductID                 int       `gorm:"index:idx_product_id;column:product_id;type:int(11);default:0" json:"productId"`                 // 产品id
-	ProductName               string    `gorm:"column:product_name;type:varchar(20);default:''" json:"productName"`                             // 产品名称
-	ModifyTime                time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                             // 修改时间
-	CompanyContractID         int       `gorm:"column:company_contract_id;type:int(11);default:0" json:"companyContractId"`                     // 合同id
-	Status                    string    `gorm:"column:status;type:enum('正式','试用','关闭','永续','潜在')" json:"status"`
+	CompanyReportPermissionId int64 `orm:"column(company_report_permission_id);pk"`
+	CompanyId                 int
+	ReportPermissionId        int
+	CreatedTime               time.Time
+	LastUpdatedTime           time.Time
+	ChartPermissionId         int
+	StartDate                 string    `description:"权限开始日期"`
+	EndDate                   string    `description:"权限结束日期"`
+	ProductId                 int       `description:"产品id"`
+	ProductName               string    `description:"产品名称"`
+	CompanyContractId         int       `description:"合同id"`
+	Status                    string    `description:"'正式','试用','关闭'"`
+	ModifyTime                time.Time `description:"修改时间"`
 }
 
-// TableName get sql table name.获取数据库表名
-func (m *CompanyReportPermission) TableName() string {
-	return "company_report_permission"
-}
-
-// CompanyReportPermissionColumns get sql column name.获取数据库列名
-var CompanyReportPermissionColumns = struct {
-	CompanyReportPermissionID string
-	CompanyID                 string
-	ReportPermissionID        string
-	CreatedTime               string
-	LastUpdatedTime           string
-	ChartPermissionID         string
-	StartDate                 string
-	EndDate                   string
-	ProductID                 string
-	ProductName               string
-	ModifyTime                string
-	CompanyContractID         string
-	Status                    string
-}{
-	CompanyReportPermissionID: "company_report_permission_id",
-	CompanyID:                 "company_id",
-	ReportPermissionID:        "report_permission_id",
-	CreatedTime:               "created_time",
-	LastUpdatedTime:           "last_updated_time",
-	ChartPermissionID:         "chart_permission_id",
-	StartDate:                 "start_date",
-	EndDate:                   "end_date",
-	ProductID:                 "product_id",
-	ProductName:               "product_name",
-	ModifyTime:                "modify_time",
-	CompanyContractID:         "company_contract_id",
-	Status:                    "status",
+// GetPermissionListByCompanyIdAndProductId 根据客户id和产品id获取可用的权限列表
+func GetPermissionListByCompanyIdAndProductId(companyId, productId int) (items []*CompanyReportPermission, err error) {
+	sql := ` select * from company_report_permission where company_id=? and product_id =? and status in ("试用","正式","永续") `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, companyId, productId).QueryRows(&items)
+	return
 }

+ 69 - 0
models/tables/rddp/classify/classify.go

@@ -0,0 +1,69 @@
+package classify
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type Classify struct {
+	Id                int       `orm:"column(id);pk"`
+	ClassifyName      string    `description:"分类名称"`
+	Sort              int       `json:"-"`
+	ParentId          int       `description:"父级分类id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	Abstract          string    `description:"栏目简介"`
+	Descript          string    `description:"分享描述"`
+	ReportAuthor      string    `description:"栏目作者"`
+	AuthorDescript    string    `description:"作者简介"`
+	ColumnImgUrl      string    `description:"栏目配图"`
+	HeadImgUrl        string    `description:"头部banner"`
+	AvatarImgUrl      string    `description:"头像"`
+	ReportImgUrl      string    `description:"报告配图"`
+	HomeImgUrl        string    `description:"首页配图"`
+	ClassifyLabel     string    `description:"分类标签"`
+	ShowType          int       `description:"展示类型:1-列表 2-专栏"`
+	HasTeleconference int       `description:"是否有电话会:0-否 1-是"`
+	VipTitle          string    `description:"研究员头衔"`
+	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:"小程序研报列表封面图"`
+}
+
+// ClassifyList 分类列表
+type ClassifyList struct {
+	Id           int    `orm:"column(id);pk"`
+	ClassifyName string `description:"分类名称"`
+	Sort         int    `description:"排序"`
+	ParentId     int    `description:"父级分类id"`
+	ShowType     int    `description:"展示类型:1-列表 2-专栏"`
+	Child        []*ClassifyList
+}
+
+// GetClassify 获取分类详情
+func GetClassify(classifyId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE id=? `
+	o := orm.NewOrmUsingDB("rddp")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// GetClassifyList 获取一级分类列表
+func GetClassifyList() (items []*ClassifyList, err error) {
+	sql := `SELECT id,classify_name,parent_id,show_type,sort FROM classify WHERE parent_id=0 AND classify_name != '权益研报' AND is_show=1 ORDER BY sort ASC,create_time ASC`
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetClassifyListByParentId 根据父级id获取当前下级的分类列表
+func GetClassifyListByParentId(parentId int) (items []*ClassifyList, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT id,classify_name,parent_id,show_type,sort FROM classify WHERE parent_id=? AND is_show=1 ORDER BY create_time ASC `
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}

+ 77 - 0
models/tables/rddp/report/report.go

@@ -0,0 +1,77 @@
+package report
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type Report struct {
+	Id                 int       `orm:"column(id)" description:"报告Id"`
+	AddType            int       `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:"频度"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	State              int       `description:"1:未发布,2:已发布"`
+	PublishTime        time.Time `description:"发布时间"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `description:"消息是否已发送,0:否,1:是"`
+	ThsMsgIsSend       int       `description:"客户群消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	VideoSize          string    `description:"音频文件大小,单位M"`
+	ContentSub         string    `description:"内容前两个章节"`
+	ReportVersion      int       `description:"1:旧版,2:新版"`
+	HasChapter         int       `description:"是否有章节 0-否 1-是"`
+	ChapterType        string    `description:"章节类型 day-晨报 week-周报"`
+	OldReportId        int       `description:"research_report表ID(后续一两个版本过渡需要,之后可移除)"`
+}
+
+// ReportList 报告列表
+type ReportList struct {
+	Id         int       `description:"报告Id"`
+	Title      string    `description:"标题"`
+	Author     string    `description:"作者"`
+	Stage      int       `description:"期数" json:"-"`
+	CreateTime time.Time `description:"创建时间" json:"create_time"`
+	HttpUrl    string    `description:"跳转地址" json:"http_url"`
+}
+
+// GetReportList 获取报告列表
+func GetReportList(condition string, pars []interface{}, startSize, pageSize int) (total int, items []*ReportList, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	// 汇总数据
+	totalSql := `SELECT count(1) total FROM report WHERE 1=1`
+	//报告列表
+	sql := `SELECT id,title,author,stage,create_time FROM report WHERE 1=1  `
+	if condition != "" {
+		totalSql += condition
+		sql += condition
+	}
+
+	err = o.Raw(totalSql, pars).QueryRow(&totalSql)
+	if err != nil {
+		return
+	}
+
+	sql += `ORDER BY modify_time DESC LIMIT ?,?`
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetById 根据报告id获取报告详情
+func GetById(id int) (item *Report, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	//报告列表
+	sql := `SELECT * FROM report WHERE id = ?  `
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}

+ 84 - 0
models/tables/rddp/report_chapter/report_chapter.go

@@ -0,0 +1,84 @@
+package report_chapter
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_open_api/utils"
+	"time"
+)
+
+// ReportChapter 报告章节
+type ReportChapter struct {
+	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
+	ReportId          int       `description:"报告ID"`
+	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
+	ClassifyIdFirst   int       `description:"一级分类id"`
+	ClassifyNameFirst string    `description:"一级分类名称"`
+	TypeId            int       `description:"品种ID"`
+	TypeName          string    `description:"品种名称"`
+	Title             string    `description:"标题"`
+	Abstract          string    `description:"摘要"`
+	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
+	Author            string    `description:"作者"`
+	Content           string    `description:"内容"`
+	ContentSub        string    `description:"内容前两个章节"`
+	Stage             int       `description:"期数"`
+	Trend             string    `description:"趋势观点"`
+	Sort              int       `description:"排序: 数值越小越靠前"`
+	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
+	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
+	PublishTime       time.Time `description:"发布时间"`
+	VideoUrl          string    `description:"音频文件URL"`
+	VideoName         string    `description:"音频文件名称"`
+	VideoPlaySeconds  string    `description:"音频播放时长"`
+	VideoSize         string    `description:"音频文件大小,单位M"`
+	CreateTime        string    `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+}
+
+// GetListByReportId 根据报告ID获取章节列表
+func GetListByReportId(reportId int, classifyNameFirst string) (list []*ReportChapter, err error) {
+	var where string
+	if classifyNameFirst == "周报" {
+		where = "report_id = ? AND is_edit = 1 AND publish_state = 2"
+	} else {
+		where = "report_id = ? AND publish_state = 2"
+	}
+
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter WHERE   ` + where
+	sql += ` order by sort asc,report_chapter_id asc  `
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+	return
+}
+
+// GetContentById 根据ID获取章节详情
+func GetContentById(id int, typeIds []int) (info *ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	lenNum := len(typeIds)
+	if lenNum <= 0 {
+		return
+	}
+	sql := `SELECT * FROM report_chapter WHERE  report_chapter_id = ? and type_id in (` + utils.GetOrmInReplace(lenNum) + `) AND publish_state = 2 `
+	err = o.Raw(sql, id, typeIds).QueryRow(&info)
+	return
+}
+
+// GetListByReportIdTypeIds 根据报告ID、章节类型ID获取章节列表
+func GetListByReportIdTypeIds(reportId int, typeIds []int, classifyNameFirst string) (list []*ReportChapter, err error) {
+	lenNum := len(typeIds)
+	if lenNum <= 0 {
+		return
+	}
+	var where string
+	if classifyNameFirst == "周报" {
+		where = `report_id = ? AND type_id in (` + utils.GetOrmInReplace(lenNum) + `) AND is_edit = 1 AND publish_state = 2 `
+	} else {
+		where = ` report_id = ? AND type_id in (` + utils.GetOrmInReplace(lenNum) + `) AND publish_state = 2 `
+	}
+
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter WHERE   ` + where
+	sql += ` order by sort asc,report_chapter_id asc  `
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+	return
+}

+ 56 - 0
models/tables/report_chapter_type/report_chapter_type.go

@@ -0,0 +1,56 @@
+package report_chapter_type
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ReportChapterType struct {
+	ReportChapterTypeId    uint64    `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         time.Time `description:"暂停开始日期"`
+	PauseEndTime           time.Time `description:"暂停结束日期"`
+	IsSet                  int       `description:"是否设置:0为设置,1已设置"`
+	YbIconUrl              string    `description:"研报小程序3.0图标"`
+	YbBottomIcon           string    `description:"研报小程序3.0底部菜单图标"`
+}
+
+// GetEffectTypes 获取列表数据
+func GetEffectTypes() (list []*ReportChapterType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM report_chapter_type WHERE is_show=?  `
+	_, err = o.Raw(sql, 1).QueryRows(&list)
+	return
+}
+
+// GetEffectTypeID 获取章节id
+func GetEffectTypeID() (chapterIds []int, err error) {
+	var chapterList []*ReportChapterType
+	o := orm.NewOrm()
+	sql := `SELECT * FROM report_chapter_type WHERE is_show=?  `
+	_, err = o.Raw(sql, 1).QueryRows(&chapterList)
+	if err != nil {
+		return
+	}
+	if len(chapterList) > 0 {
+		for _, v := range chapterList {
+			chapterIds = append(chapterIds, int(v.ReportChapterTypeId))
+		}
+	}
+	return
+}

+ 9 - 0
models/tables/wx_user/wx_user.go

@@ -20,6 +20,7 @@ type WxUser struct {
 	DepartmentName   string `description:"联系人部门"`
 	RegisterTime     time.Time
 	RegisterPlatform int
+	Enabled          int8 `description:"用户状态"`
 }
 
 type OpenIdList struct {
@@ -97,3 +98,11 @@ func GetWxUserByMobileCountryCode(mobile, countryCode string) (item *WxUser, err
 	err = o.Raw(sql, mobile).QueryRow(&item)
 	return
 }
+
+// GetByUserId 根据user_id获取用户信息
+func GetByUserId(userId int) (wxUser *WxUser, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM wx_user WHERE user_id = ? LIMIT 1 `
+	err = o.Raw(sql, userId).QueryRow(&wxUser)
+	return
+}

+ 118 - 0
routers/commentsRouter.go

@@ -0,0 +1,118 @@
+package routers
+
+import (
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/context/param"
+)
+
+func init() {
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:Admin"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:Admin"],
+        beego.ControllerComments{
+            Method: "Create",
+            Router: `/create`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:CompanyUser"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:CompanyUser"],
+        beego.ControllerComments{
+            Method: "GetUserReportList",
+            Router: `/user_report_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:CompanyUser"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:CompanyUser"],
+        beego.ControllerComments{
+            Method: "GetUserReportViewTotalList",
+            Router: `/view_total_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:QuanShiControllerCommon"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:QuanShiControllerCommon"],
+        beego.ControllerComments{
+            Method: "CallBack",
+            Router: `/callback`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "ArticleChange",
+            Router: `/article/change`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "ClassifyList",
+            Router: `/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "ListReport",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "ListReportV2",
+            Router: `/list/v2`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"],
+        beego.ControllerComments{
+            Method: "GetResearchReportChapter",
+            Router: `/getReportChapterInfo`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"],
+        beego.ControllerComments{
+            Method: "GetResearchReportChapterV2",
+            Router: `/getReportChapterInfo/v2`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"],
+        beego.ControllerComments{
+            Method: "GetReportInfo",
+            Router: `/getReportInfo`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"] = append(beego.GlobalControllerRouter["hongze/hongze_open_api/controllers:ReportControllerCommon"],
+        beego.ControllerComments{
+            Method: "GetReportInfoV2",
+            Router: `/getReportInfo/v2`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+}

+ 353 - 0
services/company/permission.go

@@ -0,0 +1,353 @@
+package company
+
+import (
+	"fmt"
+	"hongze/hongze_open_api/models/response/report"
+	"hongze/hongze_open_api/models/tables/admin"
+	"hongze/hongze_open_api/models/tables/company"
+	"hongze/hongze_open_api/models/tables/company_product"
+	"hongze/hongze_open_api/models/tables/company_report_permission"
+	"hongze/hongze_open_api/models/tables/wx_user"
+	"hongze/hongze_open_api/utils"
+)
+
+var (
+	CheckTypeApply   = "apply"
+	CheckTypeContact = "contact"
+	CheckTypeExpire  = "expired"
+)
+
+// PermissionCheckInfo 权限校验完成后的结果
+type PermissionCheckInfo struct {
+	Name         string       `json:"name" description:"销售名称"`
+	Mobile       string       `json:"mobile" description:"手机号"`
+	Type         string       `json:"type" description:"校验失败,没有权限,需要让前端处理的类型,枚举值:apply,contact"`
+	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   int    `json:"is_suspend" description:"启用与否字段:1:暂停,0:启用"`
+	HasApply    bool   `json:"has_apply" description:"是否有申请过"`
+}
+
+// CheckPermissionByPermissionIdList2Ficc 根据权限id集合权限校验(ficc)
+func CheckPermissionByPermissionIdList2Ficc(companyId int, userId int, permissionIdList []int) (ok bool, permissionCheckInfo PermissionCheckInfo, err error) {
+	defer func() {
+		//// 如果无权限,那么就去查询是否申请过
+		//if ok == false {
+		//	ok, _ = checkPermissionByPermissionIdList2Rai(companyId, userId, permissionIdList)
+		//}
+		//if ok == false && permissionCheckInfo.Type == CheckTypeApply {
+		//	_, err = yb_apply_record.GetLastNotOpRecordByUserId(userId) // 从来源我的/活动申请的记录
+		//	if err != nil && err != utils.ErrNoRow {
+		//		return
+		//	}
+		//	//查询是否有申请过,如果有申请过的话,那么err是nil
+		//	if err == nil {
+		//		permissionCheckInfo.CustomerInfo.HasApply = true
+		//	}
+		//}
+	}()
+	//非潜在客户
+	if len(permissionIdList) <= 0 {
+		err = fmt.Errorf("权限异常,请传入需要校验的权限")
+		return
+	}
+
+	permissionMap := make(map[int]bool)
+	for _, permissionId := range permissionIdList {
+		permissionMap[permissionId] = true
+	}
+	productId := 1
+	if companyId > 1 {
+		//查询是否 开通ficc的客户
+		companyProductInfo, tmpErr := company_product.GetCompanyProductByCompanyIdAndProductId(companyId, productId)
+		if tmpErr != nil {
+			// 没有开通ficc的客户
+			if tmpErr.Error() == utils.NotEmpty() {
+				permissionCheckInfo.Type = CheckTypeApply
+				return
+			}
+			err = tmpErr
+			return
+		}
+
+		wxUser, tmpErr := wx_user.GetByUserId(userId)
+		if tmpErr != nil {
+			permissionCheckInfo.Type = CheckTypeApply
+			err = tmpErr
+			return
+		}
+
+		// 查询用户是否为弘则研究已禁用的联系人
+		if companyId == 16 {
+			if wxUser.Enabled != 1 {
+				permissionCheckInfo.Type = CheckTypeApply
+				return
+			}
+		}
+
+		//客户信息
+		companyInfo, tmpErr := company.GetCompanyById(companyId)
+		if tmpErr != nil {
+			// 没有开通ficc的客户
+			if tmpErr.Error() == utils.ErrNoRow() {
+				permissionCheckInfo.Type = CheckTypeApply
+				return
+			}
+			err = tmpErr
+			return
+		}
+		customerInfo := CustomerInfo{
+			CompanyName: companyInfo.CompanyName,
+			Status:      companyProductInfo.Status,
+			Name:        wxUser.RealName,
+			IsSuspend:   companyProductInfo.IsSuspend,
+			Mobile:      wxUser.Mobile,
+		}
+		permissionCheckInfo.CustomerInfo = customerInfo
+
+		// 如果客户ficc产品的状态是流失,那么也是让去申请
+		if companyProductInfo.Status == "流失" {
+			permissionCheckInfo.Type = CheckTypeApply
+			return
+		}
+
+		//查找对应客户的销售信息
+		adminInfo, tmpErr := admin.GetByAdminId(companyProductInfo.SellerId)
+		if tmpErr != nil {
+			//if tmpErr ==
+			err = tmpErr
+			return
+		}
+
+		permissionCheckInfo.Name = adminInfo.RealName
+		permissionCheckInfo.Mobile = adminInfo.Mobile
+		if companyProductInfo.Status == "冻结" {
+			permissionCheckInfo.Type = CheckTypeContact
+			return
+		}
+
+		//客户状态是:试用暂停状态(联系销售)
+		if companyProductInfo.Status == "试用" && companyProductInfo.IsSuspend == 1 {
+			permissionCheckInfo.Type = CheckTypeContact
+			return
+		}
+
+		// 获取有效的权限id列表
+		validPermissionIdList, tmpErr := GetValidPermissionIdListByCompany2ProductId(companyId, productId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 校验在有效的权限id列表中是否存在该权限
+		for _, validPermissionId := range validPermissionIdList {
+			//如果有该权限id,那么直接返回校验通过
+			if _, validOk := permissionMap[validPermissionId]; validOk {
+				ok = true
+				return
+			}
+		}
+		permissionCheckInfo.Type = CheckTypeContact
+	} else {
+		permissionCheckInfo.Type = CheckTypeApply
+	}
+
+	return
+}
+
+// checkPermissionByPermissionIdList2Rai 根据权限id集合权限校验(权益)
+func checkPermissionByPermissionIdList2Rai(companyId int, userId int, permissionIdList []int) (ok bool, err error) {
+	//非潜在客户
+	if len(permissionIdList) <= 0 {
+		err = fmt.Errorf("权限异常,请传入需要校验的权限")
+		return
+	}
+
+	// 查询用户是否为弘则研究已禁用的联系人
+	wxUser, tmpErr := wx_user.GetByUserId(userId)
+	if tmpErr != nil {
+		err = fmt.Errorf("用户信息异常")
+		return
+	}
+	if companyId == 16 {
+		if wxUser.Enabled != 1 {
+			return
+		}
+	}
+
+	//市场策略(ficc权限id):33
+	ficcPermissionId := 33
+	//市场策略(权益权限id):23
+	raiPermissionId := 23
+
+	//是否往下校验
+	var permissionOk bool
+	for _, permissionId := range permissionIdList {
+		if permissionId == ficcPermissionId {
+			permissionOk = true
+		}
+	}
+	productId := 2
+	if companyId > 1 && permissionOk {
+		// 获取有效的权限id列表
+		validPermissionIdList, tmpErr := GetValidPermissionIdListByCompany2ProductId(companyId, productId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 校验在有效的权限id列表中是否存在该权限
+		for _, validPermissionId := range validPermissionIdList {
+			if validPermissionId == raiPermissionId {
+				ok = true
+				return
+			}
+		}
+	}
+
+	return
+}
+
+func GetCheckPermission(companyId int, userId int, permissionIdList []int) (ok bool, permissionCheckInfo report.PermissionCheckInfo, finalValidPermissionIds []int, err error) {
+	defer func() {
+		// 如果无权限,那么就去查询是否申请过
+		//if ok == false {
+		//	ok, _ = checkPermissionByPermissionIdList2Rai(companyId, userId, permissionIdList)
+		//}
+		//if ok == false && permissionCheckInfo.Type == CheckTypeApply {
+		//	_, err = yb_apply_record.GetLastNotOpRecordByUserId(userId) // 从来源我的/活动申请的记录
+		//	if err != nil {
+		//		if err == utils.ErrNoRow {
+		//			err = nil
+		//		}
+		//		return
+		//	}
+		//	//查询是否有申请过,如果有申请过的话,那么err是nil
+		//	if err == nil {
+		//		permissionCheckInfo.CustomerInfo.HasApply = true
+		//	}
+		//}
+	}()
+	permissionCheckInfo.HzPhone = utils.HZPHONE
+	//非潜在客户
+	permissionMap := make(map[int]bool)
+	if len(permissionIdList) > 0 {
+		for _, permissionId := range permissionIdList {
+			permissionMap[permissionId] = true
+		}
+	}
+
+	productId := 1
+	if companyId > 1 {
+		//查询是否 开通ficc的客户
+		companyProductInfo, tmpErr := company_product.GetCompanyProductByCompanyIdAndProductId(companyId, productId)
+		if tmpErr != nil {
+			// 没有开通ficc的客户
+			if tmpErr.Error() == utils.ErrNoRow() {
+				permissionCheckInfo.Type = CheckTypeApply
+				return
+			}
+			err = tmpErr
+			return
+		}
+
+		wxUser, tmpErr := wx_user.GetByUserId(userId)
+		if tmpErr != nil {
+			permissionCheckInfo.Type = CheckTypeApply
+			err = tmpErr
+			return
+		}
+
+		//客户信息
+		companyInfo, tmpErr := company.GetCompanyById(companyId)
+		if tmpErr != nil {
+			// 没有开通ficc的客户
+			if tmpErr.Error() == utils.ErrNoRow() {
+				permissionCheckInfo.Type = CheckTypeApply
+				return
+			}
+			err = tmpErr
+			return
+		}
+		customerInfo := report.CustomerInfo{
+			CompanyName: companyInfo.CompanyName,
+			Status:      companyProductInfo.Status,
+			Name:        wxUser.RealName,
+			IsSuspend:   companyProductInfo.IsSuspend,
+			Mobile:      wxUser.Mobile,
+		}
+		permissionCheckInfo.CustomerInfo = customerInfo
+
+		// 如果客户ficc产品的状态是流失,那么也是让去申请
+		if companyProductInfo.Status == "流失" {
+			permissionCheckInfo.Type = CheckTypeApply
+			return
+		}
+
+		//查找对应客户的销售信息
+		adminInfo, tmpErr := admin.GetByAdminId(companyProductInfo.SellerId)
+		if tmpErr != nil {
+			//if tmpErr ==
+			err = tmpErr
+			return
+		}
+
+		permissionCheckInfo.Name = adminInfo.RealName
+		permissionCheckInfo.Mobile = adminInfo.Mobile
+		if companyProductInfo.Status == "冻结" {
+			permissionCheckInfo.Type = CheckTypeContact
+			return
+		}
+
+		//客户状态是:试用暂停状态(联系销售)
+		if companyProductInfo.Status == "试用" && companyProductInfo.IsSuspend == 1 {
+			permissionCheckInfo.Type = CheckTypeContact
+			return
+		}
+
+		// 获取有效的权限id列表
+		validPermissionIdList, tmpErr := GetValidPermissionIdListByCompany2ProductId(companyId, productId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 校验在有效的权限id列表中是否存在该权限
+		if len(permissionIdList) > 0 {
+			for _, validPermissionId := range validPermissionIdList {
+				//如果有该权限id,那么直接返回校验通过
+				if _, validOk := permissionMap[validPermissionId]; validOk {
+					finalValidPermissionIds = append(finalValidPermissionIds, validPermissionId)
+					ok = true
+				}
+			}
+			return
+		}
+
+		permissionCheckInfo.Type = CheckTypeContact
+	} else {
+		permissionCheckInfo.Type = CheckTypeApply
+	}
+	return
+}
+
+// GetValidPermissionIdListByCompany2ProductId 根据客户id和产品id获取有效的权限id列表
+func GetValidPermissionIdListByCompany2ProductId(companyId, productId int) (list []int, err error) {
+	companyReportPermissionList, err := GetValidPermissionByCompany2ProductId(companyId, productId)
+	if err != nil {
+		return
+	}
+	for _, v := range companyReportPermissionList {
+		list = append(list, v.ChartPermissionId)
+	}
+	return
+}
+
+// GetValidPermissionByCompany2ProductId 根据客户id和产品id获取有效的权限列表
+func GetValidPermissionByCompany2ProductId(companyId, productId int) (list []*company_report_permission.CompanyReportPermission, err error) {
+	return company_report_permission.GetPermissionListByCompanyIdAndProductId(companyId, productId)
+}

+ 9 - 0
utils/common.go

@@ -748,3 +748,12 @@ func TrimStr(str string) (str2 string) {
 	}
 	return strings.Replace(str, " ", "", -1)
 }
+
+// GetOrmInReplace 获取orm的in查询替换?的方法
+func GetOrmInReplace(num int) string {
+	template := make([]string, num)
+	for i := 0; i < num; i++ {
+		template[i] = "?"
+	}
+	return strings.Join(template, ",")
+}

+ 6 - 0
utils/constants.go

@@ -11,6 +11,7 @@ const (
 	FormatDateTime        = "2006-01-02 15:04:05"     //完整时间格式
 	HlbFormatDateTime     = "2006-01-02_15:04:05.999" //完整时间格式
 	FormatDateTimeUnSpace = "20060102150405"          //完整时间格式
+	FormatMonthDate       = "0102"                    //月日格式
 	PageSize15            = 15                        //列表页每页数据量
 	PageSize5             = 5
 	PageSize10            = 10
@@ -100,3 +101,8 @@ const (
 const (
 	CACHE_KEY_ADMIN = "calendar:admin:list" //系统用户列表缓存key
 )
+
+const ALIYUN_YBIMG_HOST = "https://hzstatic.hzinsights.com/static/yb_wx/"
+const HZ_DEFAULT_AVATAR = "https://hzstatic.hzinsights.com/static/yb_wx/hz_default_avatar.png"
+
+const HZPHONE = "057187186319" //弘则电话