Browse Source

Merge branch 'master' into yb/5.0

hsun 2 years ago
parent
commit
ce4c06da36
65 changed files with 2404 additions and 250 deletions
  1. 170 0
      controller/comment/comment.go
  2. 27 0
      controller/like/like.go
  3. 113 0
      controller/message/message.go
  4. 280 2
      controller/pc/pc.go
  5. 31 2
      controller/user/user.go
  6. 1 1
      core/run_server.go
  7. 6 0
      init_serve/router.go
  8. 15 1
      logic/report/research_report.go
  9. 106 2
      logic/user/user.go
  10. 14 3
      middleware/token.go
  11. 14 3
      middleware/token_no_login.go
  12. 15 0
      models/request/comment/comment.go
  13. 9 0
      models/request/like/like.go
  14. 9 0
      models/request/message/message.go
  15. 5 0
      models/request/user/user.go
  16. 2 1
      models/response/classify.go
  17. 39 0
      models/response/comment.go
  18. 6 0
      models/response/like.go
  19. 23 0
      models/response/message.go
  20. 8 0
      models/response/pc/wechat.go
  21. 2 0
      models/response/permission.go
  22. 8 4
      models/response/report.go
  23. 19 0
      models/tables/chart_permission_first/chart_permission_first.go
  24. 12 0
      models/tables/chart_permission_first/query.go
  25. 26 23
      models/tables/rddp/classify/classify.go
  26. 2 2
      models/tables/rddp/classify/query.go
  27. 10 0
      models/tables/rddp/report/query.go
  28. 13 1
      models/tables/rddp/report_chapter/query.go
  29. 6 0
      models/tables/rddp/session/query.go
  30. 7 0
      models/tables/wx_user/create.go
  31. 6 0
      models/tables/wx_user/query.go
  32. 39 38
      models/tables/yb_activity/query.go
  33. 4 1
      models/tables/yb_activity/yb_activity.go
  34. 8 0
      models/tables/yb_comment/create.go
  35. 97 0
      models/tables/yb_comment/query.go
  36. 42 0
      models/tables/yb_comment/update.go
  37. 32 0
      models/tables/yb_comment/yb_comment.go
  38. 8 0
      models/tables/yb_like/create.go
  39. 45 0
      models/tables/yb_like/query.go
  40. 9 0
      models/tables/yb_like/update.go
  41. 21 0
      models/tables/yb_like/yb_like.go
  42. 55 0
      models/tables/yb_message/query.go
  43. 25 0
      models/tables/yb_message/update.go
  44. 25 0
      models/tables/yb_message/yb_message.go
  45. 15 0
      routers/comment.go
  46. 12 0
      routers/like.go
  47. 15 0
      routers/message.go
  48. 3 0
      routers/pc.go
  49. 1 0
      routers/user.go
  50. 324 0
      services/comment/comment.go
  51. 18 28
      services/company/permission.go
  52. 130 0
      services/like/like.go
  53. 159 0
      services/message/message.go
  54. 7 55
      services/pc/classify.go
  55. 7 39
      services/report/classify.go
  56. 11 4
      services/report/report.go
  57. 10 4
      services/report/report_chapter.go
  58. 1 7
      services/report/report_view_log.go
  59. 2 13
      services/report/report_view_record.go
  60. 2 13
      services/report/user_access_record.go
  61. 2 2
      services/user/user.go
  62. 77 0
      services/wx_app/security/security.go
  63. 14 0
      services/wx_app/wx_app.go
  64. 174 0
      services/yb_common.go
  65. 6 1
      utils/constants.go

+ 170 - 0
controller/comment/comment.go

@@ -0,0 +1,170 @@
+package comment
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	reqComment "hongze/hongze_yb/models/request/comment"
+	commentService "hongze/hongze_yb/services/comment"
+	userService "hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"strconv"
+)
+
+// Comment 发布留言
+func Comment(c *gin.Context)  {
+	var req reqComment.ReqComment
+	if c.ShouldBind(&req) !=nil {
+		response.Fail("入参错误", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+	data, err := commentService.Comment(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(),c)
+		return
+	}
+	response.OkData("留言成功", data, c)
+	return
+}
+
+// Delete 删除留言
+func Delete(c *gin.Context) {
+	var req *reqComment.ReqDel
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+	err := commentService.Delete(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(),c)
+		return
+	}
+	response.Ok("删除留言成功", c)
+	return
+}
+
+// HotList 获取精选留言
+func HotList(c *gin.Context)  {
+	reqReportId := c.DefaultQuery("report_id", "")
+	reqReportChapterId := c.DefaultQuery("report_chapter_id", "")
+	reqOldReportId := c.DefaultQuery("old_report_id", "")
+	reqOldReportChapterId := c.DefaultQuery("old_report_chapter_id", "")
+	reqPageIndex := c.DefaultQuery("current_index", "1")
+	reqPageSize := c.DefaultQuery("page_size", strconv.Itoa(utils.PageSize20))
+
+	pageIndex, err := strconv.Atoi(reqPageIndex)
+	if err != nil {
+		response.Fail("请输入正确的条数限制", c)
+		return
+	}
+	pageSize, err := strconv.Atoi(reqPageSize)
+	if err != nil {
+		response.Fail("请输入正确的页码", c)
+		return
+	}
+	var (
+		reportId int
+		reportChapterId int
+		oldReportId int
+		oldReportChapterId int
+	)
+	if reqReportId != ""{
+		reportId, err = strconv.Atoi(reqReportId)
+		if err != nil {
+			response.Fail("报告ID格式有误", c)
+			return
+		}
+	}
+
+	if reqReportChapterId != "" {
+		reportChapterId, err = strconv.Atoi(reqReportChapterId)
+		if err != nil {
+			response.Fail("章节ID格式有误", c)
+			return
+		}
+	}
+
+	if reqOldReportId != ""{
+		oldReportId, err = strconv.Atoi(reqOldReportId)
+		if err != nil {
+			response.Fail("老报告ID格式有误", c)
+			return
+		}
+	}
+
+	if reqOldReportChapterId != "" {
+		oldReportChapterId, err = strconv.Atoi(reqOldReportChapterId)
+		if err != nil {
+			response.Fail("章节ID格式有误", c)
+			return
+		}
+	}
+
+	userinfo := userService.GetInfoByClaims(c)
+
+	list, err := commentService.List(userinfo, reportId, reportChapterId, oldReportId,oldReportChapterId,true, pageIndex, pageSize)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", list, c )
+	return
+}
+
+// MyList 获取我的留言
+func MyList(c *gin.Context)  {
+	reqReportId := c.DefaultQuery("report_id", "")
+	reqReportChapterId := c.DefaultQuery("report_chapter_id", "")
+
+	reqOldReportId := c.DefaultQuery("old_report_id", "")
+	reqOldReportChapterId := c.DefaultQuery("old_report_chapter_id", "")
+	var (
+		reportId int
+		reportChapterId int
+		oldReportId int
+		oldReportChapterId int
+		err error
+	)
+	if reqReportId != ""{
+		reportId, err = strconv.Atoi(reqReportId)
+		if err != nil {
+			response.Fail("报告ID格式有误", c)
+			return
+		}
+	}
+
+	if reqReportChapterId != "" {
+		reportChapterId, err = strconv.Atoi(reqReportChapterId)
+		if err != nil {
+			response.Fail("章节ID格式有误", c)
+			return
+		}
+	}
+
+	if reqOldReportId != ""{
+		oldReportId, err = strconv.Atoi(reqOldReportId)
+		if err != nil {
+			response.Fail("老报告ID格式有误", c)
+			return
+		}
+	}
+
+	if reqOldReportChapterId != "" {
+		oldReportChapterId, err = strconv.Atoi(reqOldReportChapterId)
+		if err != nil {
+			response.Fail("章节ID格式有误", c)
+			return
+		}
+	}
+
+	userinfo := userService.GetInfoByClaims(c)
+
+	list, err := commentService.MyList(userinfo, reportId, reportChapterId, oldReportId,oldReportChapterId)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", list, c )
+	return
+}

+ 27 - 0
controller/like/like.go

@@ -0,0 +1,27 @@
+package like
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/models/request/like"
+	likeService "hongze/hongze_yb/services/like"
+	userService "hongze/hongze_yb/services/user"
+)
+
+// SetLike 点赞设置
+func SetLike(c *gin.Context)  {
+	var req like.ReqLike
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	userinfo := userService.GetInfoByClaims(c)
+
+	data, err := likeService.SetLike(userinfo, req)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.OkData("操作成功", data, c )
+	return
+}

+ 113 - 0
controller/message/message.go

@@ -0,0 +1,113 @@
+package message
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	message2 "hongze/hongze_yb/models/request/message"
+	"hongze/hongze_yb/services/message"
+	userService "hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"strconv"
+	"strings"
+)
+
+func List(c *gin.Context)  {
+	reqType := c.DefaultQuery("type", "0")
+	reqPageIndex := c.DefaultQuery("current_index", "1")
+	reqPageSize := c.DefaultQuery("page_size", strconv.Itoa(utils.PageSize20))
+
+	if !strings.Contains("0,1,2", reqType) {
+		response.Fail("请输入正确的消息类型", c)
+		return
+	}
+	msgtype, err := strconv.Atoi(reqType)
+	if err != nil {
+		response.Fail("请输入正确的消息类型", c)
+		return
+	}
+
+	pageIndex, err := strconv.Atoi(reqPageIndex)
+	if err != nil {
+		response.Fail("请输入正确的条数限制", c)
+		return
+	}
+	pageSize, err := strconv.Atoi(reqPageSize)
+	if err != nil {
+		response.Fail("请输入正确的页码", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+	data, err := message.GetList(userInfo, msgtype, pageIndex, pageSize)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", data, c)
+	return
+}
+
+// BatchRead 一键已读
+func BatchRead(c *gin.Context)  {
+	var req message2.ReqMessageBatch
+	if c.ShouldBind(&req) !=nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	if !strings.Contains("0,1,2", strconv.Itoa(req.Type)) {
+		response.Fail("请输入正确的消息类型", c)
+		return
+	}
+
+	userInfo := userService.GetInfoByClaims(c)
+    err := message.BatchRead(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.Ok("操作成功", c)
+	return
+}
+
+// SingleRead 设置单条消息已读
+func SingleRead(c *gin.Context)  {
+	var req message2.ReqMessage
+	if c.ShouldBind(&req) !=nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	if req.MsgId <=0 {
+		response.Fail("请输入正确的消息Id", c)
+		return
+	}
+
+	userInfo := userService.GetInfoByClaims(c)
+	err := message.SingleRead(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.Ok("操作成功", c)
+	return
+}
+
+// SingleDelete 删除单条消息
+func SingleDelete(c *gin.Context)  {
+	var req message2.ReqMessage
+	if c.ShouldBind(&req) !=nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	if req.MsgId <=0 {
+		response.Fail("请输入正确的消息Id", c)
+		return
+	}
+
+	userInfo := userService.GetInfoByClaims(c)
+	err := message.SingleDelete(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.Ok("操作成功", c)
+	return
+}

+ 280 - 2
controller/pc/pc.go

@@ -5,12 +5,15 @@ import (
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
+	userLogic "hongze/hongze_yb/logic/user"
 	pcModels "hongze/hongze_yb/models/response/pc"
 	"hongze/hongze_yb/models/tables/customer_comment"
 	"hongze/hongze_yb/models/tables/rddp/classify"
+	"hongze/hongze_yb/models/tables/rddp/msg_code"
 	"hongze/hongze_yb/models/tables/rddp/report"
 	"hongze/hongze_yb/models/tables/rddp/report_chapter"
 	"hongze/hongze_yb/models/tables/rddp/session"
+	"hongze/hongze_yb/models/tables/wx_user"
 	"hongze/hongze_yb/models/tables/wx_user_log"
 	"hongze/hongze_yb/models/tables/yb_activity"
 	"hongze/hongze_yb/models/tables/yb_pc_suncode"
@@ -492,7 +495,7 @@ func WechatLogin(c *gin.Context) {
 	fmt.Println("token:", item.Errmsg)
 	fmt.Println("token:", item.Errcode)
 	if item.Errcode != 0 {
-		response.Fail(err.Error(), c)
+		response.Fail(item.Errmsg, c)
 		return
 	}
 
@@ -550,7 +553,6 @@ QUERY_WX_USER:
 				token = tempToken
 				userId = int(tempUser.UserID)
 				isBind = true
-				return
 			}
 		}
 	} else if wxUserErr != nil {
@@ -631,3 +633,279 @@ QUERY_WX_USER:
 	response.OkData("查询成功", resp, c)
 	return
 }
+
+// @Title 登录
+// @Description 登录接口
+// @Param	request	body models.LoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /pc/pcLogin [post]
+func PcLogin(c *gin.Context) {
+	var req pcModels.PcLoginReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+
+	userId := 0
+	var isAdd bool
+	if req.LoginType == 1 {
+		if req.Mobile == "" {
+			response.Fail("请输入手机号", c)
+			return
+		}
+		if req.SmsCode == "" {
+			response.Fail("请输入有效手机验证码", c)
+			return
+		}
+		item, err := msg_code.GetMsgCode(req.Mobile, req.SmsCode)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				response.Fail("校验验证码失败,Err:" + err.Error(), c)
+				return
+			} else {
+				response.Fail("校验验证码失败,Err:" + err.Error(), c)
+				return
+			}
+		}
+		if item == nil {
+			response.Fail("手机验证码错误,请重新输入", c)
+			return
+		}
+
+		wxUser, err := wx_user.GetByMobile(req.Mobile)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				isAdd = true
+			} else {
+				response.Fail("根据手机号获取用户信息失败,Err:" + err.Error(), c)
+				return
+			}
+		}
+		if wxUser == nil {
+			isAdd = true
+		} else {
+			userId = int(wxUser.UserID)
+		}
+		//BindMobile(openId, mobile string, userId, loginType int) (err error) {
+		//newUserId, err = models.BindMobile(openId, req.Mobile, userId, req.LoginType)
+	} else if req.LoginType == 2 {
+		if req.Email == "" {
+			response.Fail("邮箱不能为空,请输入邮箱", c)
+			return
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			response.Fail("邮箱格式错误,请重新输入", c)
+			return
+		}
+		if req.SmsCode == "" {
+			response.Fail("请输入有效验证码", c)
+			return
+		}
+		item, err := msg_code.GetMsgCode(req.Email, req.SmsCode)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				response.Fail("校验验证码失败,Err:" + err.Error(), c)
+				return
+			} else {
+				response.Fail("校验验证码失败,Err:" + err.Error(), c)
+				return
+			}
+		}
+		if item == nil {
+			response.Fail("邮箱证码错误,请重新输入:", c)
+			return
+		}
+		wxUser, err := wx_user.GetByEmail(req.Email)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				isAdd = true
+			} else {
+				response.Fail("根据邮箱获取用户信息失败,Err:" + err.Error(), c)
+				return
+			}
+		}
+		if wxUser == nil {
+			isAdd = true
+		} else {
+			userId = int(wxUser.UserID)
+		}
+	} else {
+		response.Fail("无效的登录方式,loginType:" + strconv.Itoa(req.LoginType), c)
+	}
+	if isAdd {
+		user := new(wx_user.WxUser)
+		user.CompanyID = 1
+		user.CreatedTime = time.Now()
+		user.FirstLogin = 1
+		user.Enabled = 1
+		user.Email = req.Email
+		user.Mobile = req.Mobile
+		if req.LoginType == 1 {
+			user.BindAccount = user.Mobile
+		} else {
+			user.BindAccount = user.Email
+		}
+		user.RegisterTime = time.Now()
+		user.LoginTime = time.Now()
+		user.RegisterPlatform = 2
+		if req.IsFreeLogin {
+			user.IsFreeLogin = 1
+		}else {
+			user.IsFreeLogin = 0
+		}
+
+		lastId, err := user.Add()
+		if err != nil {
+			response.Fail("登录失败,新增客户信息失败,Err:" + err.Error(), c)
+			return
+		}
+		fmt.Println("lastId:", lastId)
+		userId = int(lastId)
+
+		timeUnix := time.Now().Unix()
+		timeUnixStr := strconv.FormatInt(timeUnix, 10)
+		token := utils.MD5(strconv.Itoa(userId)) + utils.MD5(timeUnixStr)
+		//新增session
+		{
+			session := new(session.Session)
+			session.UserID = int64(userId)
+			session.CreatedTime = time.Now()
+			session.LastUpdatedTime = time.Now()
+			session.ExpireTime = time.Now().AddDate(0, 3, 0)
+			session.AccessToken = token
+			err = session.Create()
+			if err != nil {
+				response.Fail("登录失败,新增用户session信息失败:" + err.Error(), c)
+				return
+			}
+		}
+	} else {
+		user := new(wx_user.WxUser)
+		user.UserID = uint64(userId)
+		if req.IsFreeLogin {
+			user.IsFreeLogin = 1
+		}else {
+			user.IsFreeLogin = 0
+		}
+
+		err := user.Update([]string{"is_free_login"})
+		if err != nil {
+			response.Fail("登录失败,修改登录信息失败,Err:" + err.Error(), c)
+			return
+		}
+	}
+	if userId == 0 {
+		response.Fail("登录失败,id为 0", c)
+		return
+	}
+
+	err := wx_user.ModifyFirstLogin(uint64(userId))
+	if err != nil {
+		response.Fail("登录失败,判断权限失败:" + err.Error(), c)
+		return
+	}
+	var token string
+	tokenItem, err := session.GetTokenByUid(userId)
+	if err != nil && err != utils.ErrNoRow {
+		response.Fail("登录失败,获取token失败:" + err.Error(), c)
+		return
+	}
+
+	if tokenItem == nil || (err != nil && err == utils.ErrNoRow) {
+		timeUnix := time.Now().Unix()
+		timeUnixStr := strconv.FormatInt(timeUnix, 10)
+		token = utils.MD5(strconv.Itoa(userId)) + utils.MD5(timeUnixStr)
+		//新增session
+		{
+			session := new(session.Session)
+			session.UserID = int64(userId)
+			session.CreatedTime = time.Now()
+			session.LastUpdatedTime = time.Now()
+			session.ExpireTime = time.Now().AddDate(0, 3, 0)
+			session.AccessToken = token
+			err = session.Create()
+			if err != nil {
+				response.Fail("登录失败,新增用户session信息失败:" + err.Error(), c)
+				return
+			}
+		}
+	} else {
+		token = tokenItem.AccessToken
+	}
+
+	//新增登录日志
+	{
+		loginLog := new(wx_user_log.WxUserLog)
+		loginLog.UserID = userId
+		loginLog.Mobile = req.Mobile
+		loginLog.Email = req.Email
+		loginLog.Handle = "pc_login"
+		loginLog.CreateTime = time.Now()
+		go loginLog.Create()
+	}
+
+	response.OkData("登录成功", token, c)
+}
+
+// GetSmsCode 获取短信验证码接口
+// @Tags 用户模块
+// @Summary  获取短信验证码
+// @Description 获取短信验证码接口
+// @Security ApiKeyAuth
+// @securityDefinitions.basic BasicAuth
+// @Param mobile	query string true "手机号"
+// @Param area_num	query string true "手机国际区号(中国大陆:86)"
+// @Accept  json
+// @Product json
+// @Success 200 {string} string 获取验证码成功
+// @Failure 400 {string} string 手机号不能为空,请输入手机号
+// @Router /pc_code/get_sms_code [get]
+func GetSmsCode(c *gin.Context) {
+	mobile := c.DefaultQuery("mobile", "")
+	areaNum := c.DefaultQuery("area_num", "")
+	err, errMsg := userLogic.PcSendSmsCode(mobile, areaNum)
+	if err != nil {
+		if errMsg != "" {
+			errMsg = "获取验证码失败"
+		}
+		response.Fail(errMsg, c)
+		return
+	}
+
+	response.Ok("获取验证码成功", c)
+}
+
+// GetEmailCode 获取邮箱验证码接口
+// @Tags 用户模块
+// @Summary  获取邮箱验证码
+// @Description 获取邮箱验证码
+// @Security ApiKeyAuth
+// @securityDefinitions.basic BasicAuth
+// @Param email	query string true "电子邮箱账号"
+// @Accept  json
+// @Product json
+// @Success 200 {string} string 获取验证码成功
+// @Failure 400 {string} string 请输入邮箱地址
+// @Router /pc_code/get_email_code [get]
+func GetEmailCode(c *gin.Context) {
+	email := c.DefaultQuery("email", "")
+	if email == "" {
+		response.Fail("请输入邮箱地址", c)
+		return
+	}
+	if !utils.ValidateEmailFormatat(email) {
+		response.Fail("邮箱格式错误,请重新输入", c)
+		return
+	}
+
+	err, errMsg := userLogic.PcSendEmailCode(email)
+	if err != nil {
+		if errMsg != "" {
+			errMsg = "获取验证码失败"
+		}
+		response.Fail(errMsg, c)
+		return
+	}
+
+	response.Ok("获取验证码成功", c)
+}

+ 31 - 2
controller/user/user.go

@@ -226,8 +226,8 @@ func Apply(c *gin.Context) {
 		return
 	}
 	userInfo := userService.GetInfoByClaims(c)
-	openId := userInfo.OpenID
-	if openId == "" {
+	userId := userInfo.UserID
+	if userId == 0 {
 		response.Fail("参数异常", c)
 		return
 	}
@@ -264,3 +264,32 @@ func GetTabBar(c *gin.Context) {
 
 	response.OkData("获取成功", tabBarList, c)
 }
+
+// SetUserInfo 设置用户个人信息(头像和昵称)
+func SetUserInfo(c *gin.Context) {
+	var req user.SetUserInfoReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	// 去掉首尾空格
+	req.NickName = strings.Trim(req.NickName, "")
+	req.HeadImgUrl = strings.Trim(req.HeadImgUrl, "")
+	if req.NickName == "" {
+		response.Fail("请输入昵称", c)
+		return
+	}
+
+	if req.HeadImgUrl == "" {
+		response.Fail("请上传头像", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+
+	err := userLogic.SetUserInfo(userInfo, req)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.Ok("更新成功", c)
+}

+ 1 - 1
core/run_server.go

@@ -20,7 +20,7 @@ func RunServe() {
 	init_serve.NewEsClient()
 
 	//启动任务
-	init_serve.InitTask()
+	//init_serve.InitTask()
 	// 3.监听端口,默认在8080
 	// Run("里面不指定端口号默认为8080")
 	err := r.Run(fmt.Sprint("0.0.0.0:", global.CONFIG.Serve.Port)) // 监听并在 0.0.0.0:8080 上启动服务

+ 6 - 0
init_serve/router.go

@@ -54,6 +54,12 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitCommunity(r)
 	// 设置静态文件夹件路径
 	r.StaticFS("/static", http.Dir("./static"))
+	// 研报点赞相关路由
+	routers.InitLike(r)
+	// 研报留言相关路由
+	routers.InitComment(r)
+	// 研报消息相关路由
+	routers.InitMessage(r)
 	//pc相关路由
 	routers.InitPc(r)
 	return

+ 15 - 1
logic/report/research_report.go

@@ -12,6 +12,7 @@ import (
 	"hongze/hongze_yb/models/tables/research_report_type"
 	"hongze/hongze_yb/models/tables/user_view_history"
 	"hongze/hongze_yb/models/tables/wx_user"
+	"hongze/hongze_yb/services"
 	"hongze/hongze_yb/utils"
 	"strconv"
 	"time"
@@ -22,6 +23,8 @@ type ResearchReportInfo struct {
 	ResearchReportTypeList        []*company_report_permission.ResearchReportTypeList `json:"research_report_type_list"`
 	HasMenu                       int                                                 `json:"has_menu"`
 	ResearchReportTypeContentList []*research_report.ResearchReportTypeContent        `description:"报告详情"`
+	LikeNum                       int64                                               `description:"点赞总数" json:"like_num"`
+	LikeEnabled                   int8                                                `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
 }
 
 // GetResearchReportInfo 获取报告详情
@@ -122,14 +125,19 @@ func GetResearchReportInfo(researchReportId, userId uint64) (result ResearchRepo
 	//添加阅读日志的数据加入到redis
 	go PushViewRecordNewRedisData(userViewHistory, int(wxUserInfo.CompanyID))
 
+	//查询点赞数
+	likeNum,likeEnabled, _ := services.GetReportLikeByReportIdOldReportId(wxUserInfo.UserID, 0, 0, int(researchReportId),0)
+
 	result = ResearchReportInfo{
 		ResearchReportInfo:     reportInfo,
 		ResearchReportTypeList: researchReportTypeList,
 		HasMenu:                1,
+		LikeNum:                likeNum,
+		LikeEnabled:            likeEnabled,
 	}
 
 	if len(researchReportTypeList) <= 0 {
-
+		
 	} else if len(researchReportTypeList) == 1 {
 		//只有一个章节,即没有目录的时候,需要直接返回章节详情
 		result.HasMenu = 0
@@ -146,6 +154,8 @@ type ResearchReportTypeContentInfo struct {
 	ResearchReportTypeInfo        *research_report_type.ResearchReportTypeInfo `json:"research_report_type_info"`
 	Add                           int                                          `json:"add"`
 	ResearchReportTypeContentList []*research_report.ResearchReportTypeContent `description:"报告详情" json:"research_report_type_content_list"`
+	LikeNum                       int64                                        `description:"点赞总数" json:"like_num"`
+	LikeEnabled                   int8                                         `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
 }
 
 // GetResearchReportTypeContentInfo 获取报告章节详情
@@ -247,10 +257,14 @@ func GetResearchReportTypeContentInfo(researchReportTypeId, userId uint64) (resu
 	//添加阅读日志的数据加入到redis
 	go PushViewRecordNewRedisData(userViewHistory, int(wxUserInfo.CompanyID))
 
+	//查询点赞数
+	likeNum,likeEnabled, _ := services.GetReportLikeByReportIdOldReportId(wxUserInfo.UserID, 0, 0, int(researchReportTypeInfo.ResearchReportID), int(researchReportTypeInfo.ResearchReportTypeID))
 	result = ResearchReportTypeContentInfo{
 		ResearchReportTypeContentList: researchReportTypeContentList,
 		ResearchReportTypeInfo:        researchReportTypeInfo,
 		Add:                           add,
+		LikeNum:                       likeNum,
+		LikeEnabled:                   likeEnabled,
 	}
 	return
 }

+ 106 - 2
logic/user/user.go

@@ -10,6 +10,7 @@ import (
 	"hongze/hongze_yb/models/tables/rddp/msg_code"
 	"hongze/hongze_yb/models/tables/wx_user"
 	"hongze/hongze_yb/models/tables/yb_apply_record"
+	"hongze/hongze_yb/models/tables/yb_message"
 	"hongze/hongze_yb/services"
 	companyService "hongze/hongze_yb/services/company"
 	"hongze/hongze_yb/services/user"
@@ -107,8 +108,12 @@ type Detail struct {
 	SellerName     string              `json:"seal_name" description:"所属销售名称"`
 	SellerMobile   string              `json:"seal_mobile" description:"所属销售手机号"`
 	PermissionList []CompanyPermission `json:"permission_list" description:"权限列表"`
-	IsInner		   int				   `json:"is_inner" description:"是否为内部员工"`
-	AdminInfo      *admin2.Admin	   `json:"admin_info" description:"系统管理员信息"`
+	IsInner        int                 `json:"is_inner" description:"是否为内部员工"`
+	AdminInfo      *admin2.Admin       `json:"admin_info" description:"系统管理员信息"`
+	UnRead         int64               `json:"un_read" description:"消息未读数"`
+	NickName       string              `json:"nick_name" description:"用户昵称"`
+	HeadImgUrl     string              `json:"head_img_url" description:"用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空"`
+	UserId         uint64              `json:"user_id" description:"用户ID"`
 }
 
 // GetUserInfo 获取用户我的页面详情数据
@@ -205,6 +210,16 @@ func GetUserInfo(userInfo user.UserInfo) (userDetail Detail, err error, errMsg s
 		isInner = 1
 	}
 
+	// 查询消息未读数
+	unRead, err := yb_message.GetUnreadByUserId(userInfo.UserID)
+	if err != nil {
+		errMsg = "查询消息未读数失败"
+		return
+	}
+	headimgurl := userInfo.Headimgurl
+	if headimgurl == "" {
+		headimgurl = utils.DEFAULT_HONGZE_USER_LOGO
+	}
 	userDetail = Detail{
 		CompanyName:    companyName, 		//客户名称(公司名称)
 		Status:         status,      		//产品状态
@@ -217,11 +232,35 @@ func GetUserInfo(userInfo user.UserInfo) (userDetail Detail, err error, errMsg s
 		PermissionList: list,				//权限列表
 		IsInner: 		isInner,			// 是否为内部员工
 		AdminInfo: 		adminInfo,			// 系统管理员信息
+		UnRead:         unRead,
+		NickName:       userInfo.NickName,
+		HeadImgUrl:     headimgurl,
+		UserId:         userInfo.UserID,
 	}
 
 	return
 }
 
+// SetUserInfo 设置用户的个人信息,头像和昵称
+func SetUserInfo(userInfo user.UserInfo, req userReq.SetUserInfoReq) (err error) {
+	// todo 用户如果没有设置头像,用默认头像也允许上传
+	// 校验昵称长度
+	// 校验头像地址是否正确
+	if !strings.Contains(req.HeadImgUrl, "http://") && !strings.Contains(req.HeadImgUrl, "https://")  {
+		err = errors.New("上传头像出错")
+		return
+	}
+	wxUser := userInfo.WxUser
+	wxUser.NickName = req.NickName
+	wxUser.Headimgurl = req.HeadImgUrl
+	err = wxUser.Update([]string{"nick_name","headimgurl"})
+	if err != nil {
+		err = errors.New("更新用户信息操作失败")
+		return
+	}
+	return
+}
+
 type Record struct {
 	BusinessCardURL string `json:"business_card_url" description:"名片"`
 	RealName        string `json:"real_name" description:"姓名"`
@@ -364,3 +403,68 @@ func GetUserTabBar(userInfo user.UserInfo, version string) (list []string, err e
 	}
 	return
 }
+
+// PcSendSmsCode 发送手机短信
+func PcSendSmsCode(mobile, areaNum string) (err error, errMsg string) {
+	if mobile == "" {
+		err = errors.New("请输入手机号")
+		return
+	}
+	msgCode := utils.GetRandDigit(4)
+	var result bool
+	if areaNum == "86" || areaNum == "" || areaNum == "0" {
+		//国内的短信
+		result = services.SendSmsCode(mobile, msgCode)
+	} else {
+		//国际短信
+		result = services.SendSmsCodeGj(mobile, msgCode, areaNum)
+	}
+	//发送成功
+	if result {
+		item := &msg_code.MsgCode{
+			Mobile:          mobile,
+			Code:            msgCode,
+			ExpiredIn:       time.Now().Add(15 * time.Minute).Unix(),
+			Enabled:         1,
+			CreatedTime:     time.Time{},
+			LastUpdatedTime: time.Time{},
+		}
+		err = item.Create()
+	} else {
+		err = errors.New("短信发送失败")
+	}
+	return
+}
+
+// PcSendEmailCode 发送邮件
+func PcSendEmailCode(email string) (err error, errMsg string) {
+	if email == "" {
+		err = errors.New("请输入邮箱地址")
+		return
+	}
+	if !utils.ValidateEmailFormatat(email) {
+		err = errors.New("邮箱格式错误,请重新输入")
+		return
+	}
+	msgCode := utils.GetRandDigit(4)
+	content := "尊敬的用户:</br>您好,感谢您使用弘则研究,您正在进行邮箱验证,本次请求的验证码为:" + msgCode + "(为了保障您账号的安全性,请在15分钟内完成验证。)</br>弘则研究团队 </br>" + time.Now().Format(utils.FormatDateCN)
+	title := "弘则研究登陆验证"
+	//发送邮件
+	result, err := services.SendEmailByHz(title, content, email)
+
+	if result {
+		item := &msg_code.MsgCode{
+			Mobile:          email,
+			Code:            msgCode,
+			ExpiredIn:       time.Now().Add(15 * time.Minute).Unix(),
+			Enabled:         1,
+			CreatedTime:     time.Time{},
+			LastUpdatedTime: time.Time{},
+		}
+		err = item.Create()
+	} else {
+		err = errors.New("发送失败,Err:" + err.Error())
+	}
+
+	return
+}

+ 14 - 3
middleware/token.go

@@ -46,10 +46,21 @@ func Token() gin.HandlerFunc {
 			tmpUserInfo, tmpErr := services.GetWxUserItemByOpenId(sessionInfo.OpenID)
 			userInfo = tmpUserInfo
 			err = tmpErr
+			if err != nil {
+				response.TokenError(nil, "数据异常!", "openid查询用户信息错误", c)
+				c.Abort()
+				return
+			}
 		} else {
-			response.TokenError(nil, "数据异常!", "openid为空", c)
-			c.Abort()
-			return
+			//判断pc端登录的情况
+			tmpUserInfo, tmpErr := services.GetWxUserItemByUserId(int(sessionInfo.UserID), 3)
+			userInfo = tmpUserInfo
+			err = tmpErr
+			if err != nil {
+				response.TokenError(nil, "数据异常!", "userID查询用户信息错误", c)
+				c.Abort()
+				return
+			}
 		}
 
 		if err != nil {

+ 14 - 3
middleware/token_no_login.go

@@ -46,10 +46,21 @@ func TokenNoLogin() gin.HandlerFunc {
 			tmpUserInfo, tmpErr := services.GetWxUserItemByOpenId(sessionInfo.OpenID)
 			userInfo = tmpUserInfo
 			err = tmpErr
+			if err != nil {
+				response.TokenError(nil, "数据异常!", "openid查询用户信息错误", c)
+				c.Abort()
+				return
+			}
 		} else {
-			response.TokenError(nil, "数据异常!", "openid为空", c)
-			c.Abort()
-			return
+			//判断pc端登录的情况
+			tmpUserInfo, tmpErr := services.GetWxUserItemByUserId(int(sessionInfo.UserID), 3)
+			userInfo = tmpUserInfo
+			err = tmpErr
+			if err != nil {
+				response.TokenError(nil, "数据异常!", "userID查询用户信息错误", c)
+				c.Abort()
+				return
+			}
 		}
 
 		//如果查询异常,且异常信息不是:用户openid查询出来发现没有绑定用户

+ 15 - 0
models/request/comment/comment.go

@@ -0,0 +1,15 @@
+package comment
+
+type ReqComment struct {
+	Content                string `description:"留言内容" json:"content"`
+	ReportId               int `description:"报告ID" json:"report_id" `
+	ReportChapterId        int `description:"报告章节ID" json:"report_chapter_id" `
+	IsShowName             int8 `description:"是否匿名 0-匿名,1-不匿名" json:"is_show_name"`
+	SourceAgent            int  `description:"留言入口来源,1:小程序,2:pc" json:"source_agent"`
+	OldReportId            int `description:"老后台报告ID (research_report_id)" json:"old_report_id" `
+	OldReportChapterId     int `description:"老后台报告章节ID(research_report_type_id)" json:"old_report_chapter_id" `
+}
+
+type ReqDel struct {
+	CommentId        uint64 `description:"留言ID" json:"comment_id"`
+}

+ 9 - 0
models/request/like/like.go

@@ -0,0 +1,9 @@
+package like
+
+type ReqLike struct {
+	ReportId               int `description:"报告ID" json:"report_id" `
+	ReportChapterId        int `description:"报告章节ID" json:"report_chapter_id" `
+	OldReportId            int `description:"老后台报告ID (research_report_id)" json:"old_report_id" `
+	OldReportChapterId     int `description:"老后台报告章节ID(research_report_type_id)" json:"old_report_chapter_id" `
+	SourceAgent            int `description:"点赞入口来源,1:小程序,2:小程序pc" json:"source_agent"`
+}

+ 9 - 0
models/request/message/message.go

@@ -0,0 +1,9 @@
+package message
+
+type ReqMessageBatch struct {
+	Type    int `description:"消息类型:1-留言回复通知,2-精选留言通知" json:"type"`
+}
+
+type ReqMessage struct {
+	MsgId   uint64 `description:"消息ID" json:"msg_id"`
+}

+ 5 - 0
models/request/user/user.go

@@ -17,3 +17,8 @@ type ApplyReq struct {
 	SourceAgent     int    `description:"申请入口来源,1:小程序,2:pc" json:"source_agent"`
 	FromPage        string `description:"申请来源页面" json:"from_page"`
 }
+
+type SetUserInfoReq struct {
+	NickName            string    `description:"用户昵称" json:"nick_name"`
+	HeadImgUrl          string    `description:"用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空" json:"head_img_url"`
+}

+ 2 - 1
models/response/classify.go

@@ -7,13 +7,14 @@ import (
 type ClassifyListItem struct {
 	ClassifyIdSecond   int    `json:"classify_id_second"`
 	ClassifyNameSecond string `json:"classify_name_second"`
+	Abstract           string `json:"abstract"`
 	ParentId           int    `json:"parent_id"`
 	ReportAuthor       string `json:"report_author"`
 	AuthorDescript     string `json:"author_descript"`
 	HomeImgUrl         string `json:"home_img_url"`
 	Stage              int    `description:"期数" json:"stage"`
 	ProductName        string `json:"product_name"`
-	VipTitle		   string `json:"vip_title"`
+	VipTitle           string `json:"vip_title"`
 }
 
 type ClassifyDetail struct {

+ 39 - 0
models/response/comment.go

@@ -0,0 +1,39 @@
+package response
+
+import "time"
+
+type RespCommentList struct {
+	List       []*RespCommentItem   `json:"list"`
+	Paging     *PagingItem  		`json:"paging"`
+}
+type RespMyCommentList struct {
+	List       []*RespCommentItem   `json:"list"`
+	IsShowName int8 `description:"是否匿名 0-匿名,1-不匿名" json:"is_show_name"`
+}
+type RespCommentItem struct {
+	CommentId  uint64    `description:"留言ID" json:"comment_id"`
+	UserId     uint64    `description:"用户id" json:"user_id"`
+	Content    string    `description:"留言内容" json:"content"`
+	IsTop      int8      `description:"是否置顶(0-未置顶,1-置顶)json:"is_top""`
+	IsHot      int8      `description:"是否设置精选(0-未设置,1-已设置)json:"is_hot""`
+	HotTopTime time.Time `description:"设置精选或者设置置顶的时间" json:"hot_top_time"`
+	IsShowName int8      `description:"是否匿名 0-匿名,1-不匿名" json:"is_show_name"`
+	UserName   string    `description:"用户昵称" json:"user_name"`
+	UserImgUrl string    `description:"用户头像" json:"user_img_url"`
+	CreateTime time.Time `description:"留言创建时间" json:"create_time"`
+	ReplyList  []*ReplyItem
+}
+
+type ReplyItem struct {
+	CommentId         uint64 `description:"留言ID" json:"comment_id"`
+	AdminId           uint64 `description:"发布留言回复的管理员ID" json:"admin_id"`
+	AdminName         string `description:"系统昵称" json:"admin_name"`
+	AdminImgUrl          string `description:"系统头像" json:"admin_img_url"`
+	Content           string `description:"回复内容" json:"content"`
+	ReplyCommentId    uint64 `description:"回复的留言ID" json:"reply_comment_id"`
+	CreateTime        time.Time `description:"留言创建时间" json:"create_time"`
+}
+
+type RespCommentAdd struct {
+	CommentId    uint64 `description:"留言ID" json:"comment_id"`
+}

+ 6 - 0
models/response/like.go

@@ -0,0 +1,6 @@
+package response
+
+type RespLike struct {
+	LikeNum  int64  `description:"点赞总数" json:"like_num"`
+	LikeEnabled  int8 `description:"本次点赞结果: 0-已取消赞 1-有效赞" json:"like_enabled"`
+}

+ 23 - 0
models/response/message.go

@@ -0,0 +1,23 @@
+package response
+
+import "time"
+
+type RespMessageItem struct {
+	MsgId              uint64    `description:"消息ID" json:"msg_id"`
+	UserId             uint64    `description:"用户ID" json:"user_id"`
+	Type               int8      `description:"消息类型:1-留言回复通知,2-精选留言通知" json:"type"`
+	CreateTime         time.Time `description:"创建时间" json:"create_time"`
+	ContentFirst       string    `description:"消息第一行留言内容" json:"content_first"`
+	ContentSecond      string    `description:"消息第二行内容" json:"content_second"`
+	IsRead             int8      `description:"是否已读 0-未读,1-已读" json:"is_read"`
+	ReportId           int       `description:"报告ID"  json:"report_id" `
+	ReportChapterId    int       `description:"报告章节ID" json:"report_chapter_id" `
+	OldReportId        int       `description:"老报告ID" json:"old_report_id"`
+	OldReportChapterId int       `description:"老报告章节ID" json:"old_report_chapter_id"`
+	Img                string    `description:"左边头像" json:"img"`
+}
+
+type RespMessageList struct {
+	List   []*RespMessageItem `json:"list"`
+	Paging *PagingItem        `json:"paging"`
+}

+ 8 - 0
models/response/pc/wechat.go

@@ -29,3 +29,11 @@ type LoginResp struct {
 	Token  string `json:"authorization"`
 	IsBind bool   `json:"is_bind"`
 }
+
+type PcLoginReq struct {
+	LoginType   int    `description:"登录方式:1:手机,2:邮箱"`
+	Mobile      string `description:"手机号"`
+	Email       string `description:"邮箱"`
+	SmsCode     string `description:"短信/邮箱验证码"`
+	IsFreeLogin bool   `description:"是否免登陆,true:免登陆,false:非免登陆"`
+}

+ 2 - 0
models/response/permission.go

@@ -5,6 +5,8 @@ type PermissionFirstItem struct {
 	Sort       int
 	IsCheck    bool
 	List       PermissionFiccSecondList
+	YbIndexName string
+	YbIndexIcon string
 }
 
 type PermissionFiccItem struct {

+ 8 - 4
models/response/report.go

@@ -9,6 +9,8 @@ type ReportDetail struct {
 	ReportChapterList []*ReportChapterListItem `json:"report_chapter_list"`
 	PermissionCheck   *PermissionCheckInfo     `json:"permission_check"`
 	AuthOk            bool                     `json:"auth_ok"`
+	LikeNum           int64                    `description:"点赞总数" json:"like_num"`
+	LikeEnabled       int8                     `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
 }
 
 type ReportChapterListItem struct {
@@ -69,10 +71,12 @@ type ReportChapterItem struct {
 }
 
 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"`
+	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"`
 }
 
 type ReportChapterMenu struct {

+ 19 - 0
models/tables/chart_permission_first/chart_permission_first.go

@@ -0,0 +1,19 @@
+package chart_permission_first
+
+import "time"
+
+// ChartPermissionFirst 报告权限一级分类表
+type ChartPermissionFirst struct {
+	Id           uint64    `gorm:"primaryKey;column:id;type:bigint(20) unsigned;not null" json:"-"`
+	ClassifyName string    `gorm:"column:classify_name;type:varchar(50)"`                                        // 权限一级分类名称,与chart_permission的classify_name一致
+	YbIndexName  string    `gorm:"column:yb_index_name;type:varchar(50);default:''" `                            // 研报小程序首页简称
+	YbIndexSort  int      `gorm:"column:yb_index_sort;type:tinyint(4);default:0"`                               // 研报小程序首页排序
+	YbIndexShow  int8      `gorm:"column:show_type;type:tinyint(4);default:0"`                                   // 是否展示在研报小程序首页页面  1-展示;0-不展示
+	YbIndexIcon  string    `gorm:"column:yb_index_icon;type:varchar(255);default:''"`                            // 研报小程序首页图标地址
+	CreateTime   time.Time `gorm:"index:create_time;column:create_time;type:datetime;default:CURRENT_TIMESTAMP"` //创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *ChartPermissionFirst) TableName() string {
+	return "chart_permission_first"
+}

+ 12 - 0
models/tables/chart_permission_first/query.go

@@ -0,0 +1,12 @@
+package chart_permission_first
+
+import (
+	"hongze/hongze_yb/global"
+)
+
+// GetIndexShowList 查询首页展示的权限一级分类
+func GetIndexShowList() (list []*ChartPermissionFirst, err error) {
+	err = global.DEFAULT_MYSQL.Model(ChartPermissionFirst{}).Where("yb_index_show = 1").Scan(&list).Error
+	return
+}
+

+ 26 - 23
models/tables/rddp/classify/classify.go

@@ -3,29 +3,32 @@ package classify
 import "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隐藏分类下的报告
+	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页面排序
 }
 
 func (c *Classify) TableName() string  {

+ 2 - 2
models/tables/rddp/classify/query.go

@@ -37,7 +37,7 @@ func GetSecondIdsByClassifyNames(names []string) (ids []int, err error) {
 // GetParentList 查询所有一级分类
 func GetParentList() (list []*Classify, err error) {
 	err = global.MYSQL["rddp"].Model(Classify{}).
-		Select("id, classify_name, show_type").
+		Select("id, classify_name, show_type, yb_ficc_icon, yb_ficc_pc_icon, yb_ficc_sort").
 		Where("parent_id = 0 and classify_name != '权益研报' AND is_show = 1").
 		Order("sort asc, id asc").Scan(&list).Error
 	if err == utils.ErrNoRow {
@@ -58,7 +58,7 @@ func GetByClassifyId(id int) (item *Classify, err error) {
 // GetListByPid 根据分类名称查找专栏列表
 func GetListByPid(pid int) (list []*Classify, err error) {
 	err = global.MYSQL["rddp"].Model(Classify{}).
-		Select("id, classify_name, parent_id, report_author, author_descript, home_img_url, vip_title, avatar_img_url").
+		Select("id, classify_name, parent_id, abstract, report_author, author_descript, home_img_url, vip_title, avatar_img_url").
 		Where("parent_id = ? AND is_show = 1 ", pid).Order("sort asc, id asc").Scan(&list).Error
 	if err == utils.ErrNoRow {
 		err = nil

+ 10 - 0
models/tables/rddp/report/query.go

@@ -315,6 +315,16 @@ WHERE
 	return
 }
 
+// GetReportByOldReportId 根据老后台的research_report_id查找新的报告ID
+func GetReportByOldReportId(oldReportId uint64)(item *Report, err error)  {
+	err = global.MYSQL["rddp"].Model(Report{}).
+		Where("old_report_id=?", oldReportId).First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
 // GetLatestReportByPermission 根据权限相关的分类查询最新的三篇专栏报告
 func GetLatestReportByPermission(classifyIdSeconds []int) (list []*pc.LatestReport, err error)  {
 	sql := `SELECT

+ 13 - 1
models/tables/rddp/report_chapter/query.go

@@ -83,7 +83,7 @@ func GetReportIdsByTypeIdsAndClass(typeIds []int, classifyNameFirst string) (rep
 
 // GetTypeIdById 根据ID获取章节类型
 func GetTypeIdById(id int) (info *ReportChapter, err error)  {
-	err = global.MYSQL["rddp"].Model(ReportChapter{}).Select("report_chapter_id, type_id").
+	err = global.MYSQL["rddp"].Model(ReportChapter{}).Select("report_chapter_id, report_id, type_id").
 		Where("report_chapter_id = ? AND publish_state = 2 ", id).
 		First(&info).Error
 	if err == utils.ErrNoRow {
@@ -116,6 +116,18 @@ func GetByTypeIdsAndReportIds(typeIds []int,  reportIds []int, classifyNameFirst
 	return
 }
 
+// GetChapterByReportIdTypeId 根据报告ID和章节类型ID查找章节
+func GetChapterByReportIdTypeId(reportId, typeId int) (chapter *ReportChapter, err error) {
+	err = global.MYSQL["rddp"].Model(ReportChapter{}).
+		Select("report_id, type_id, report_chapter_id").
+		Where("report_id = ? and type_id = ?", reportId, typeId).
+		First(&chapter).Error
+	if err == utils.ErrNoRow {
+		err =nil
+	}
+	return
+}
+
 func GetWeekRecommendList(reportId int, firstName string) (items []*ReportChapter, err error) {
 	sql := `SELECT * FROM (SELECT
 	a.report_id,

+ 6 - 0
models/tables/rddp/session/query.go

@@ -22,3 +22,9 @@ func GetTokenByToken(token string) (item *Session, err error) {
 func getDb() *gorm.DB {
 	return global.MYSQL["rddp"]
 }
+
+// GetTokenByUid 根据用户id获取token
+func GetTokenByUid(userId int) (item *Session, err error) {
+	err = getDb().Where("user_id = ? ", userId).First(&item).Error
+	return
+}

+ 7 - 0
models/tables/wx_user/create.go

@@ -7,3 +7,10 @@ func (wxUser *WxUser) Create() (err error) {
 	err = global.DEFAULT_MYSQL.Create(wxUser).Error
 	return
 }
+
+//  Create 新增记录
+func (wxUser *WxUser) Add() (id uint64,err error) {
+	err = global.DEFAULT_MYSQL.Create(wxUser).Error
+	id = wxUser.UserID
+	return
+}

+ 6 - 0
models/tables/wx_user/query.go

@@ -34,3 +34,9 @@ func GetByUserId(userId int) (wxUser *WxUser, err error) {
 	err = global.DEFAULT_MYSQL.Where("user_id =  ? ", userId).First(&wxUser).Error
 	return
 }
+
+// GetByUserIds 根据user_id获取用户信息
+func GetByUserIds(userIds []uint64) (list []*WxUser, err error) {
+	err = global.DEFAULT_MYSQL.Model(WxUser{}).Where("user_id in  ? ", userIds).Scan(&list).Error
+	return
+}

+ 39 - 38
models/tables/yb_activity/query.go

@@ -6,40 +6,42 @@ import (
 )
 
 type ActivityItem struct {
-	ActivityID          	int       	`json:"activityId"`
-	FirstActivityTypeID   	int       	`json:"firstActivityTypeId"`	// 第一级的活动类型ID
-	FirstActivityTypeName 	string    	`json:"firstActivityTypeName"`	// 第一级的活动类型名称
-	ActivityName        	string    	`json:"activityName"`			// 活动名称
-	ActivityTypeID			int			`json:"activityTypeId"`			// 活动类型ID
-	ActivityTypeName    	string    	`json:"activityTypeName"`		// 活动类型名称
-	StartTime           	time.Time 	`json:"startTime"`				// 活动开始时间
-	EndTime             	time.Time 	`json:"endTime"`				// 活动结束时间
-	Speaker             	string    	`json:"speaker"`				// 主讲人
-	SpeakerHeadPic			string		`json:"speakerHeadPic"`			// 主讲人头像
-	SpeakerBackgroundPic	string		`json:"speakerBackgroundPic"`	// 主讲人背景图
-	City                	string		`json:"city"`					// 城市
-	WeekString				string		`json:"weekString"`				// 周几
-	HasRemind				int		  	`json:"hasRemind"`				// 是否已提醒
-	HasPlayBack				int		  	`json:"hasPlayBack"`			// 是否有回放
-	RegisterState			int		  	`json:"registerState"`			// 报名状态 0-取消报名 1-已报名
-	ActivityState			int			`json:"activityState"`			// 活动状态 1-本周预告 2-进行中 3-已结束
+	ActivityID            int       `json:"activityId"`
+	FirstActivityTypeID   int       `json:"firstActivityTypeId"`   // 第一级的活动类型ID
+	FirstActivityTypeName string    `json:"firstActivityTypeName"` // 第一级的活动类型名称
+	ActivityName          string    `json:"activityName"`          // 活动名称
+	ActivityTypeID        int       `json:"activityTypeId"`        // 活动类型ID
+	ActivityTypeName      string    `json:"activityTypeName"`      // 活动类型名称
+	StartTime             time.Time `json:"startTime"`             // 活动开始时间
+	EndTime               time.Time `json:"endTime"`               // 活动结束时间
+	Speaker               string    `json:"speaker"`               // 主讲人
+	SpeakerHeadPic        string    `json:"speakerHeadPic"`        // 主讲人头像
+	SpeakerBackgroundPic  string    `json:"speakerBackgroundPic"`  // 主讲人背景图
+	City                  string    `json:"city"`                  // 城市
+	WeekString            string    `json:"weekString"`            // 周几
+	HasRemind             int       `json:"hasRemind"`             // 是否已提醒
+	HasPlayBack           int       `json:"hasPlayBack"`           // 是否有回放
+	RegisterState         int       `json:"registerState"`         // 报名状态 0-取消报名 1-已报名
+	ActivityState         int       `json:"activityState"`         // 活动状态 1-本周预告 2-进行中 3-已结束
 }
 
 type ActivityDetail struct {
 	ActivityItem
-	MainlandTel			string		`json:"mainlandTel"`		// 大陆拨入
-	HongKongTel         string		`json:"hongKongTel"`		// 香港拨入
-	TaiwanTel           string		`json:"taiwanTel"`			// 台湾拨入
-	AmericaTel          string		`json:"americaTel"`			// 美国拨入
-	SingaporeTel        string		`json:"singaporeTel"`		// 新加坡拨入
-	ParticipationCode   string		`json:"participationCode"`	// 参会密码
-	LinkParticipants    string		`json:"linkParticipants"`	// 参会链接
-	IsLimitPeople       int8		`json:"isLimitPeople"`		// 是否限制人数 1是,0否
-	LimitPeopleNum      int			`json:"limitPeopleNum"`		// 限制人数数量
-	ReportLink          string		`json:"reportLink"`			// 报告链接
-	ReportName			string		`json:"reportName"`			// 报告名称
-	Address             string		`json:"address"`			// 活动地址
-	RegisteredNum		int			`json:"registeredNum"`		// 已报名人数
+	MainlandTel       string `json:"mainlandTel"`       // 大陆拨入
+	HongKongTel       string `json:"hongKongTel"`       // 香港拨入
+	TaiwanTel         string `json:"taiwanTel"`         // 台湾拨入
+	AmericaTel        string `json:"americaTel"`        // 美国拨入
+	SingaporeTel      string `json:"singaporeTel"`      // 新加坡拨入
+	ParticipationCode string `json:"participationCode"` // 参会密码
+	LinkParticipants  string `json:"linkParticipants"`  // 参会链接
+	IsLimitPeople     int8   `json:"isLimitPeople"`     // 是否限制人数 1是,0否
+	LimitPeopleNum    int    `json:"limitPeopleNum"`    // 限制人数数量
+	ReportLink        string `json:"reportLink"`        // 报告链接
+	ReportName        string `json:"reportName"`        // 报告名称
+	Address           string `json:"address"`           // 活动地址
+	RegisteredNum     int    `json:"registeredNum"`     // 已报名人数
+	ReportId          int    `json:"report_id"`         // 报告ID
+	IsNewReport       int    `json:"is_new_report"`     // 是否关联新报告
 }
 
 // GetPageListByWhere 分页获取活动列表
@@ -60,7 +62,7 @@ func GetPageListByWhere(condition string, pars []interface{}, page, limit int, o
 func GetDetailById(activityId int) (activity *ActivityDetail, err error) {
 	fields := []string{
 		"activity_id", "activity_name", "activity_type_id", "activity_type_name", "start_time", "end_time", "speaker", "city", "speaker_head_pic", "speaker_background_pic",
-		"mainland_tel", "hong_kong_tel", "taiwan_tel", "america_tel", "singapore_tel", "participation_code",
+		"mainland_tel", "hong_kong_tel", "taiwan_tel", "america_tel", "singapore_tel", "participation_code", "report_id", "is_new_report",
 		"link_participants", "is_limit_people", "limit_people_num", "report_link", "report_name", "address", "first_activity_type_id", "first_activity_type_name",
 	}
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).Select(fields).Where("activity_id", activityId).Scan(&activity).Error
@@ -74,7 +76,7 @@ func GetOneById(activityId int) (activity *YbActivity, err error) {
 }
 
 // GetActivityByIDsAndDate 根据时间和活动ID筛选出合适的记录
-func GetActivityByIDsAndDate( ids []int, publishTime string) (list []*YbActivity, err error) {
+func GetActivityByIDsAndDate(ids []int, publishTime string) (list []*YbActivity, err error) {
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).
 		Select("DISTINCT activity_id").
 		Where("activity_id in (?) and publish_status = 1 and create_time > ? and is_delete = 0", ids, publishTime).Scan(&list).Error
@@ -82,13 +84,13 @@ func GetActivityByIDsAndDate( ids []int, publishTime string) (list []*YbActivity
 }
 
 // GetLatestByIds 获取最新的活动
-func GetLatestByIds(activityids []int) (activity *YbActivity, err error)  {
+func GetLatestByIds(activityids []int) (activity *YbActivity, err error) {
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).Where("activity_id in (?) and is_delete = 0 and publish_status = 1", activityids).Order("create_time desc").First(&activity).Error
 	return
 }
 
 // GetListByIds 分页查询活动列表
-func GetListByIds(activityids []int, offset , limit int) (activitys []*YbActivity, err error)  {
+func GetListByIds(activityids []int, offset, limit int) (activitys []*YbActivity, err error) {
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).
 		Where("activity_id in (?) and is_delete = 0 and publish_status = 1", activityids).
 		Order("create_time desc").
@@ -99,16 +101,15 @@ func GetListByIds(activityids []int, offset , limit int) (activitys []*YbActivit
 }
 
 // GetListCountByIds 查询活动列表总数
-func GetListCountByIds(activityIds []int) (total int64, err error)  {
+func GetListCountByIds(activityIds []int) (total int64, err error) {
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).
 		Where("activity_id in (?) and is_delete = 0 and publish_status = 1", activityIds).
 		Count(&total).Error
 	return
 }
 
-
 // GetLatestActivity 获取最新的活动
-func GetLatestActivity() (activity *YbActivity, err error)  {
+func GetLatestActivity() (activity *YbActivity, err error) {
 	err = global.DEFAULT_MYSQL.Model(YbActivity{}).Where("is_delete = 0 and publish_status = 1").Order("create_time desc").First(&activity).Error
 	return
-}
+}

+ 4 - 1
models/tables/yb_activity/yb_activity.go

@@ -6,7 +6,7 @@ import (
 
 // YbActivity 弘则研小程序 活动表
 type YbActivity struct {
-	ActivityID            int       `gorm:"primaryKey;column:activity_id;type:int(11);not null" json:"activityID"`                                                     // 活动ID
+	ActivityID            int       `gorm:"primaryKey;column:activity_id;type:int(11);not null" json:"activityID"`                                            // 活动ID
 	FirstActivityTypeID   int       `gorm:"index:activity_type_id;column:first_activity_type_id;type:int(100);not null;default:0" json:"firstActivityTypeId"` // 第一级的活动类型ID
 	FirstActivityTypeName string    `gorm:"column:first_activity_type_name;type:varchar(30);not null;default:''" json:"firstActivityTypeName"`                // 第一级的活动类型名称
 	ActivityTypeID        int       `gorm:"column:activity_type_id;type:int(100);not null;default:0" json:"activityTypeId"`                                   // 活动类型ID
@@ -39,6 +39,7 @@ type YbActivity struct {
 	IsDelete              int8      `gorm:"column:is_delete;type:tinyint(4);not null;default:0" json:"isDelete"`                                              // 是否删除,0:未删除,1:已删除
 	ModifyTime            time.Time `gorm:"column:modify_time;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"modifyTime"`                           // 修改时间
 	CreateTime            time.Time `gorm:"index:create_time;column:create_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createTime"`                   // 创建时间
+	IsNewReport           int       `gorm:"column:is_new_report;type:tinyint(4);not null;default:0" json:"isNewReport"`                                       // 是否关联新报告:0-否 1-是
 }
 
 // TableName get sql table name.获取数据库表名
@@ -81,6 +82,7 @@ var YbActivityColumns = struct {
 	IsDelete              string
 	ModifyTime            string
 	CreateTime            string
+	IsNewReport           string
 }{
 	ActivityID:            "activity_id",
 	FirstActivityTypeID:   "first_activity_type_id",
@@ -115,4 +117,5 @@ var YbActivityColumns = struct {
 	IsDelete:              "is_delete",
 	ModifyTime:            "modify_time",
 	CreateTime:            "create_time",
+	IsNewReport:           "is_new_report",
 }

+ 8 - 0
models/tables/yb_comment/create.go

@@ -0,0 +1,8 @@
+package yb_comment
+
+import "hongze/hongze_yb/global"
+
+func (yc *YbComment) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(yc).Error
+	return
+}

+ 97 - 0
models/tables/yb_comment/query.go

@@ -0,0 +1,97 @@
+package yb_comment
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+
+// GetListByUserIdReportId 获取用户的留言列表
+func GetListByUserIdReportId(userId uint64, reportId, reportChapterId int) (list []*YbComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("user_id = ? and report_id = ? and report_chapter_id = ? and enabled = 1 ", userId, reportId, reportChapterId).
+		Order("create_time desc, comment_id desc").
+		Scan(&list).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetListByUserIdOldReportId 获取用户的留言列表
+func GetListByUserIdOldReportId(userId uint64, oldReportId, oldReportChapterId int) (list []*YbComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("user_id = ? and old_report_id = ? and old_report_chapter_id = ? and enabled = 1 ", userId, oldReportId, oldReportChapterId).
+		Order("create_time desc, comment_id desc").
+		Scan(&list).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetHotListByReportId 获取报告的精选留言列表
+func GetHotListByReportId(reportId, reportChapterId int, offset, limit int) (list []*YbComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("report_id = ? and report_chapter_id = ? and enabled = 1 and is_hot = 1 and type = 1", reportId, reportChapterId).
+		Order("is_top desc, hot_top_time desc, comment_id desc").
+		Offset(offset).
+		Limit(limit).
+		Scan(&list).Error
+	return
+}
+
+// GetHotListTotalByReportId 获取精选留言总条数
+func GetHotListTotalByReportId(reportId, reportChapterId int)(total int64, err error)  {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("report_id = ? and report_chapter_id = ? and enabled = 1 and is_hot = 1 and type = 1", reportId, reportChapterId).
+		Count(&total).Error
+	return
+}
+
+// GetHotListByOldReportId 获取老报告的精选留言列表
+func GetHotListByOldReportId(oldReportId, oldReportChapterId int, offset, limit int) (list []*YbComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("old_report_id = ? and old_report_chapter_id = ? and enabled = 1 and is_hot = 1 and type = 1", oldReportId, oldReportChapterId).
+		Order("is_top desc, hot_top_time desc, comment_id desc").
+		Offset(offset).
+		Limit(limit).
+		Scan(&list).Error
+	return
+}
+
+// GetHotListTotalByOldReportId 获取老报告的精选留言总条数
+func GetHotListTotalByOldReportId(oldReportId, oldReportChapterId int)(total int64, err error)  {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("old_report_id = ? and old_report_chapter_id = ? and enabled = 1 and is_hot = 1 and type = 1", oldReportId, oldReportChapterId).
+		Count(&total).Error
+	return
+}
+
+// GetReplyListByReplyCommentId 获取报告的精选留言的回复列表
+func GetReplyListByReplyCommentId(replyCommentIds []uint64) (list []*YbComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Where("enabled = 1 and type = 2 and reply_comment_id in ?", replyCommentIds).
+		Order("comment_id asc").
+		Scan(&list).Error
+	return
+}
+
+// GetSimpleByCommentId 根据留言ID,查询留言
+func GetSimpleByCommentId(commentId uint64)(item *YbComment, err error)  {
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Select("comment_id, user_id, type, enabled").
+		Where("comment_id = ?", commentId).First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetMyLatestComment 获取用户最新的留言
+func GetMyLatestComment(userId uint64) (item *YbComment, err error){
+	err = global.DEFAULT_MYSQL.Model(YbComment{}).
+		Select("comment_id, user_id, type, enabled, is_show_name").
+		Where("user_id = ? and type=1", userId).Order("comment_id desc").First(&item).Error
+	return
+}

+ 42 - 0
models/tables/yb_comment/update.go

@@ -0,0 +1,42 @@
+package yb_comment
+
+import "hongze/hongze_yb/global"
+
+// Update 更新对应字段数据
+/*func (yc *YbComment) Update(updateCols []string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(yc).Select(updateCols).Updates(*yc).Error
+	return
+}*/
+
+// Delete 软删除,隐藏评论
+func Delete(userId uint64, commentId uint64)(err error) {
+	tx := global.DEFAULT_MYSQL.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	sql1 := ` UPDATE yb_comment
+			SET
+            	enabled = 0,
+				modify_time = NOW(),
+				is_hot = 0,
+				is_top = 0
+			WHERE type = 1 and user_id = ? and comment_id = ?`
+	err = tx.Exec(sql1, userId, commentId).Error
+	if err != nil {
+		return
+	}
+	// 删除相关联的回复
+	sql2 := ` UPDATE yb_comment
+			SET
+            	enabled = 0,
+				modify_time = NOW()
+			WHERE reply_comment_id = ? and type = 2`
+	err = tx.Exec(sql2, commentId).Error
+	return
+}
+
+

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

@@ -0,0 +1,32 @@
+package yb_comment
+
+import "time"
+
+// 研报 用户留言表
+type YbComment struct {
+	CommentId                 uint64 `gorm:"primaryKey;column:comment_id;type:bigint(20) unsigned;not null" ` //留言ID
+	UserId                    uint64 `gorm:"column:user_id"` //用户id
+	AdminId                   uint64 `gorm:"column:admin_id"` //发布留言回复的管理员ID
+	ReportId                  int `gorm:"column:report_id"` //报告ID
+	ReportChapterId           int `gorm:"column:report_chapter_id"` //报告章节ID
+	Content                   string `gorm:"column:content"` //留言内容
+	SysIsRead                 int8 `gorm:"column:sys_is_read"` //管理员是否已读 0-未读,1-已读
+	SysReadTime               time.Time `gorm:"column:sys_read_time"` //管理员已读时间
+	SysReadAdminId            int64 `gorm:"column:sys_read_admin_id"` //已读的管理员id
+	ReplyCommentId            uint64 `gorm:"column:reply_comment_id"` //回复的留言ID
+	IsTop                     int8 `gorm:"column:is_top"` //是否置顶(0-未置顶,1-置顶)
+	IsHot                     int8 `gorm:"column:is_hot"` //是否设置精选(0-未设置,1-已设置)
+	HotTopTime                time.Time `gorm:"column:hot_top_time"` //设置精选或者设置置顶的时间
+	Type                      int8 `gorm:"column:type"` //留言类型 1-评论 2-回复
+	Enabled                   int8 `gorm:"column:enabled"` //是否有效, 0-无效留言 1-有效留言
+	IsShowName                int8 `gorm:"column:is_show_name"` //是否匿名 0-匿名,1-不匿名
+	SourceAgent               int `gorm:"column:source_agent"` //留言入口来源,1:小程序,2:pc
+	CreateTime                time.Time `gorm:"column:create_time"` //创建时间
+	ModifyTime                time.Time `gorm:"column:modify_time"` //修改时间
+	OldReportId               int `gorm:"column:old_report_id"  json:"old_report_id" ` //老报告ID
+	OldReportChapterId        int `gorm:"column:old_report_chapter_id" json:"old_report_chapter_id" ` //老报告章节ID
+}
+
+func (yc *YbComment) TableName() string {
+	return "yb_comment"
+}

+ 8 - 0
models/tables/yb_like/create.go

@@ -0,0 +1,8 @@
+package yb_like
+
+import "hongze/hongze_yb/global"
+
+func (yl *YbLike) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(yl).Error
+	return
+}

+ 45 - 0
models/tables/yb_like/query.go

@@ -0,0 +1,45 @@
+package yb_like
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+
+// GetLikeByUserIdAndReportId 获取点赞记录
+func GetLikeByUserIdAndReportId(userId uint64, reportId, reportChapterId int) (item *YbLike, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbLike{}).
+		Where("user_id = ? and report_id = ? and report_chapter_id = ?", userId, reportId, reportChapterId).
+		First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetLikeByUserIdAndOldReportId 获取点赞记录
+func GetLikeByUserIdAndOldReportId(userId uint64, oldReportId, oldReportChapterId int) (item *YbLike, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbLike{}).
+		Where("user_id = ? and old_report_id = ? and old_report_chapter_id = ?", userId, oldReportId, oldReportChapterId).
+		First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetLikeNumByReportId 统计报告的点赞数
+func GetLikeNumByReportId(reportId, reportChapterId int) (num int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbLike{}).
+		Where("report_id = ? and report_chapter_id = ? and enabled=1", reportId, reportChapterId).
+		Count(&num).Error
+	return
+}
+
+// GetLikeNumByOldReportId 统计报告的点赞数
+func GetLikeNumByOldReportId(oldReportId, oldReportChapterId int) (num int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbLike{}).
+		Where("old_report_id = ? and old_report_chapter_id = ? and enabled=1", oldReportId, oldReportChapterId).
+		Count(&num).Error
+	return
+}

+ 9 - 0
models/tables/yb_like/update.go

@@ -0,0 +1,9 @@
+package yb_like
+
+import "hongze/hongze_yb/global"
+
+// Update 更新对应字段数据
+func (yl *YbLike) Update(updateCols []string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(yl).Select(updateCols).Updates(*yl).Error
+	return
+}

+ 21 - 0
models/tables/yb_like/yb_like.go

@@ -0,0 +1,21 @@
+package yb_like
+
+import "time"
+
+// YbLike 研报 点赞
+type YbLike struct {
+	LikeId                 uint64 `gorm:"primaryKey;column:like_id;type:bigint(20) unsigned;not null" json:"like_id" ` //消息序号
+	UserId                 uint64 `gorm:"column:user_id"  json:"user_id" ` //用户id
+	Enabled                int8 `gorm:"column:enabled"  json:"enabled" ` //状态. 0-已取消赞 1-有效赞
+	CreateTime             time.Time `gorm:"column:create_time"  json:"create_time" ` //创建时间
+	ModifyTime             time.Time `gorm:"column:modify_time"  json:"modify_time" ` //修改时间
+	ReportId               int `gorm:"column:report_id"  json:"report_id" ` //报告ID
+	ReportChapterId        int `gorm:"column:report_chapter_id" json:"report_chapter_id" ` //报告章节ID
+	SourceAgent            int `gorm:"column:source_agent"` //留言入口来源,1:小程序,2:pc
+	OldReportId               int `gorm:"column:old_report_id"  json:"old_report_id" ` //老报告ID
+	OldReportChapterId        int `gorm:"column:old_report_chapter_id" json:"old_report_chapter_id" ` //老报告章节ID
+}
+
+func (yl *YbLike) TableName() string {
+	return "yb_like"
+}

+ 55 - 0
models/tables/yb_message/query.go

@@ -0,0 +1,55 @@
+package yb_message
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+// GetUnreadByUserId 获取用户的未读数
+func GetUnreadByUserId(UserId uint64) (total int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbMessage{}).
+		Where("user_id = ? and enabled = 1 and is_read=0", UserId).
+		Count(&total).Error
+	return
+}
+
+// GetListByType 根据消息类型查询用户消息列表
+func GetListByType(userId uint64, msgType int, offset, limit int) (list []*YbMessage, err error) {
+	var pars []interface{}
+	pars = append(pars, userId)
+	sql := ` SELECT * FROM yb_message 
+WHERE user_id = ? and enabled = 1 `
+	if msgType > 0 {
+		sql += " and type= ?"
+		pars = append(pars, msgType)
+	}
+	sql += " GROUP BY create_time desc, msg_id desc LIMIT ?,? "
+	pars = append(pars, offset, limit)
+	err = global.DEFAULT_MYSQL.Raw(sql, pars...).Scan(&list).Error
+	return
+}
+
+// GetListTotalByType 根据消息类型查询用户消息列表总数
+func GetListTotalByType(userId uint64, msgType int) (total int64, err error) {
+	var pars []interface{}
+	pars = append(pars, userId)
+	sql := ` SELECT count(*) FROM yb_message 
+WHERE user_id = ? and enabled = 1 `
+	if msgType > 0 {
+		sql += " and type= ?"
+		pars = append(pars, msgType)
+	}
+	err = global.DEFAULT_MYSQL.Raw(sql, pars...).Count(&total).Error
+	return
+}
+
+// GetMsgByMsgId 根据消息ID查询消息详情
+func GetMsgByMsgId(userId, msgId uint64) (item *YbMessage, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbMessage{}).
+		Where("user_id = ? and msg_id = ?", userId, msgId).
+		First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}

+ 25 - 0
models/tables/yb_message/update.go

@@ -0,0 +1,25 @@
+package yb_message
+
+import (
+	"hongze/hongze_yb/global"
+)
+
+// Update 更新对应字段数据
+func (ym *YbMessage) Update(updateCols []string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(ym).Select(updateCols).Updates(*ym).Error
+	return
+}
+
+// SetBatchRead 批量设置已读
+func SetBatchRead(userId uint64, msgType int)(err error) {
+	var pars []interface{}
+	pars = append(pars, userId)
+	sql := ` UPDATE yb_message set is_read = 1, modify_time=NOW()
+WHERE user_id = ? and is_read = 0 `
+	if msgType > 0 {
+		sql += " and type= ?"
+		pars = append(pars, msgType)
+	}
+	err = global.DEFAULT_MYSQL.Exec(sql, pars...).Error
+	return
+}

+ 25 - 0
models/tables/yb_message/yb_message.go

@@ -0,0 +1,25 @@
+package yb_message
+
+import "time"
+
+// 研报 消息表
+type YbMessage struct {
+	MsgId              uint64    `gorm:"primaryKey;column:msg_id"`     //消息序号
+	UserId             uint64    `gorm:"column:user_id"`               //用户id
+	Type               int8      `gorm:"column:type"`                  //消息类型:1-留言回复通知,2-精选留言通知
+	Enabled            int8      `gorm:"column:enabled"`               //是否有效, 0-无效 1-有效
+	CreateTime         time.Time `gorm:"column:create_time"`           //创建时间
+	ModifyTime         time.Time `gorm:"column:modify_time"`           //修改时间
+	CommentId          uint64    `gorm:"column:comment_id"`            //留言ID
+	IsRead             int8      `gorm:"column:is_read"`               //是否已读 0-未读,1-已读
+	ContentFirst       string    `gorm:"column:content_first"`         //消息第一行留言内容
+	ContentSecond      string    `gorm:"column:content_second"`        //消息第二行内容
+	ReportId           int       `gorm:"column:report_id"`             //报告ID
+	ReportChapterId    int       `gorm:"column:report_chapter_id"`     //报告章节ID
+	OldReportId        int       `gorm:"column:old_report_id"`         //老报告ID
+	OldReportChapterId int       `gorm:"column:old_report_chapter_id"` //老报告章节ID
+}
+
+func (ym *YbMessage) TableName() string {
+	return "yb_message"
+}

+ 15 - 0
routers/comment.go

@@ -0,0 +1,15 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/comment"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitComment(r *gin.Engine)  {
+	rGroup := r.Group("/api/comment").Use(middleware.Token())
+	rGroup.POST("/set", comment.Comment)
+	rGroup.POST("/del", comment.Delete)
+	rGroup.GET("/hot", comment.HotList)
+	rGroup.GET("/my", comment.MyList)
+}

+ 12 - 0
routers/like.go

@@ -0,0 +1,12 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/like"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitLike(r *gin.Engine)  {
+	rGroup := r.Group("api/like").Use(middleware.Token())
+	rGroup.POST("/set", like.SetLike)      //点赞设置
+}

+ 15 - 0
routers/message.go

@@ -0,0 +1,15 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/message"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitMessage(r *gin.Engine)  {
+	rGroup := r.Group("/api/message").Use(middleware.Token())
+	rGroup.GET("/list", message.List)
+	rGroup.POST("/batch/read", message.BatchRead)
+	rGroup.POST("/read", message.SingleRead)
+	rGroup.POST("/delete", message.SingleDelete)
+}

+ 3 - 0
routers/pc.go

@@ -19,4 +19,7 @@ func InitPc(r *gin.Engine)  {
 	rGroup.POST("/getSunCode", pc.GetSunCode)
 	pcGroup := r.Group("api/pc")
 	pcGroup.GET("/login", pc.WechatLogin)
+	pcGroup.GET("/get_sms_code", pc.GetSmsCode)
+	pcGroup.GET("/get_email_code", pc.GetEmailCode)
+	pcGroup.POST("/pcLogin", pc.PcLogin)
 }

+ 1 - 0
routers/user.go

@@ -41,6 +41,7 @@ func initUser(r *gin.Engine) {
 		rGroup2.GET("/get_last_apply_record", user.GetLastApplyRecord)
 		rGroup2.POST("/apply", user.Apply)
 		rGroup2.GET("/get_tab_bar", user.GetTabBar)
+		rGroup2.POST("/set", user.SetUserInfo)
 	}
 
 }

+ 324 - 0
services/comment/comment.go

@@ -0,0 +1,324 @@
+package comment
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	reqComment "hongze/hongze_yb/models/request/comment"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/wx_user"
+	"hongze/hongze_yb/models/tables/yb_comment"
+	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/services/wx_app"
+	"hongze/hongze_yb/utils"
+	"strconv"
+	"time"
+)
+
+// Comment 发布留言
+func Comment(user user.UserInfo, req reqComment.ReqComment) (ret response.RespCommentAdd, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("Comment: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	//校验请求入参
+	if req.IsShowName != 0 && req.IsShowName != 1 {
+		err = errors.New("匿名设置出错")
+		return
+	}
+	if req.Content == "" {
+		err = errors.New("请输入留言内容")
+		return
+	}
+	reportId := req.ReportId
+	reportChapterId := req.ReportChapterId
+
+	if req.SourceAgent == 0 {
+		err = errors.New("请输入留言来源")
+		return
+	}
+	if req.ReportChapterId <=0 && req.ReportId <=0 && req.OldReportId <=0 && req.OldReportChapterId <=0{
+		err = errors.New("请输入报告ID")
+		return
+	}
+	if req.ReportId <=0 && req.OldReportId <= 0 {
+		err = errors.New("请输入报告ID")
+		return
+	}
+	// 判断是否有留言权限
+	err, errMsg = services.CheckSimpleCompanyProduct(user)
+	if err != nil {
+		return
+	}
+	//处理老报告, 转化成新报告ID
+	if req.ReportChapterId <=0 && req.ReportId <=0 && (req.OldReportId >0 || req.OldReportChapterId > 0) {
+		reportId, reportChapterId, err, errMsg = services.GetReportIdReportChapterIdByOldReportId(uint64(req.OldReportId), uint64(req.OldReportChapterId))
+		if err != nil {
+			return
+		}
+	} else {
+		// 判断报告ID是否正确
+		err, errMsg = services.CheckReportExistByReportIdReportChapterId(reportId, reportChapterId)
+		if err != nil {
+			return
+		}
+	}
+	// 敏感词过滤
+	if user.RecordInfo.OpenID != "" && user.RecordInfo.CreatePlatform == 6 {   //只有小程序的用户才能走敏感词过滤接口
+		checkResult, tErr := wx_app.MsgSecCheck(user.RecordInfo.OpenID, req.Content)
+		/*if tErr != nil {
+			errMsg = "敏感词过滤失败" + tErr.Error()
+			err = errors.New("敏感词过滤失败")
+			return
+		}*/
+		if tErr == nil {
+			if checkResult.Result != nil {
+				if checkResult.Result.Suggest != "pass" {
+					errMsg = "含有违禁词,不允许发布:" + checkResult.Result.Suggest +".命中标签:"+strconv.Itoa(checkResult.Result.Label)
+					err = errors.New("含有违禁词,不允许发布。")
+					return
+				}
+			}
+		}
+	}
+
+
+	//新增留言
+	now := time.Now()
+	commentInfo := &yb_comment.YbComment{
+		UserId: user.UserID,
+		Content: req.Content,
+		ReportId: reportId,
+		ReportChapterId: reportChapterId,
+		IsShowName: req.IsShowName,
+		SourceAgent: req.SourceAgent,
+		Type: 1,
+		Enabled: 1,
+		CreateTime: now,
+		ModifyTime: now,
+		OldReportId:    req.OldReportId,
+		OldReportChapterId: req.OldReportChapterId,
+	}
+	err = commentInfo.Create()
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("新增留言出错")
+		return
+	}
+	ret.CommentId = commentInfo.CommentId
+	return
+}
+
+// Delete 删除留言
+func Delete(user user.UserInfo, req *reqComment.ReqDel) (err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("comment Delete: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	if req.CommentId <= 0 {
+		err = errors.New("请输入留言ID")
+		return
+	}
+	//校验请求入参
+	commentInfo, err := yb_comment.GetSimpleByCommentId(req.CommentId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询留言出错")
+		return
+	}
+	if commentInfo.CommentId <= 0 {
+		err = errors.New("留言不存在")
+		return
+	}
+	if commentInfo.UserId != user.UserID {
+		err = errors.New("不允许删除他人的留言")
+		return
+	}
+	if commentInfo.Type != 1 {
+		err = errors.New("不允许删除回复")
+		return
+	}
+	if commentInfo.Enabled == 0 {
+		return
+	}
+	err = yb_comment.Delete(user.UserID, commentInfo.CommentId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("删除留言出错")
+		return
+	}
+	return
+}
+
+// MyList 我的留言列表
+func MyList(user user.UserInfo,  reportId, reportChapterId, oldReportId, oldReportChapterId int) (ret response.RespMyCommentList, err error) {
+	list, err := List(user, reportId, reportChapterId, oldReportId, oldReportChapterId, false, 0, 0)
+	if err != nil {
+		return
+	}
+	//查询我的最新一条留言是否勾选匿名的设置
+	lastComment, tErr := yb_comment.GetMyLatestComment(user.UserID)
+	if tErr == nil {
+		ret.IsShowName = lastComment.IsShowName
+	}
+	ret.List = list.List
+	return
+}
+
+// List 查询精选留言列表或我的留言列表
+func List(user user.UserInfo,  reportId, reportChapterId, oldReportId, oldReportChapterId int, hotFlag bool, pageIndex, pageSize int) (ret response.RespCommentList, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("comment List: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+
+	if reportId <=0 && reportChapterId <=0 && oldReportId <=0 && oldReportChapterId <=0{
+		err = errors.New("请输入报告ID")
+		return
+	}
+	if reportId <=0 && oldReportId <= 0 {
+		err = errors.New("请输入报告ID")
+		return
+	}
+	//处理老报告, 转化成新报告ID
+	if  reportId <=0 && reportChapterId <=0 && (oldReportId >0 || oldReportChapterId > 0) {
+		reportId, reportChapterId, err, errMsg = services.GetReportIdReportChapterIdByOldReportId(uint64(oldReportId), uint64(oldReportChapterId))
+		if err != nil {
+			return
+		}
+	} else {
+		// 判断报告ID是否正确
+		err, errMsg = services.CheckReportExistByReportIdReportChapterId(reportId, reportChapterId)
+		if err != nil {
+			return
+		}
+	}
+	offset := (pageIndex -1)*pageSize
+	var commentList []*yb_comment.YbComment
+	var total int64
+	//查询精选留言
+	if hotFlag {
+		if reportId > 0 {
+			commentList, err = yb_comment.GetHotListByReportId(reportId, reportChapterId, offset, pageSize)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言列表出错")
+				return
+			}
+			total, err = yb_comment.GetHotListTotalByReportId(reportId, reportChapterId)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言总数出错")
+				return
+			}
+		}else {
+			commentList, err = yb_comment.GetHotListByOldReportId(oldReportId, oldReportChapterId, offset, pageSize)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言列表出错")
+				return
+			}
+			total, err = yb_comment.GetHotListTotalByOldReportId(oldReportId, oldReportChapterId)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言总数出错")
+				return
+			}
+		}
+	} else {
+		//查询个人留言
+		if reportId > 0{
+			commentList, err = yb_comment.GetListByUserIdReportId(user.UserID, reportId, reportChapterId)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言列表出错")
+				return
+			}
+		}else {
+			commentList, err = yb_comment.GetListByUserIdOldReportId(user.UserID, oldReportId, oldReportChapterId)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("查询精选留言列表出错")
+				return
+			}
+		}
+
+	}
+
+	var commentIds []uint64
+	var userIds []uint64
+	for _, v := range commentList {
+		commentIds = append(commentIds, v.CommentId)
+		userIds = append(userIds, v.UserId)
+	}
+	// 查询所有的回复列表
+	replyListMap := make(map[uint64][]*response.ReplyItem)
+	if len(commentIds) > 0 {
+		replyList, tErr := yb_comment.GetReplyListByReplyCommentId(commentIds)
+		if tErr != nil {
+			errMsg = tErr.Error()
+			err = errors.New("查询回复出错")
+			return
+		}
+		for _, v := range replyList {
+			t := new(response.ReplyItem)
+			t.CommentId = v.CommentId
+			t.Content = v.Content
+			t.AdminId = v.AdminId
+			t.CreateTime = v.CreateTime
+			t.ReplyCommentId = v.ReplyCommentId
+			t.AdminName = "弘则研究"
+			t.AdminImgUrl = utils.DEFAULT_HONGZE_SYS_LOGO
+			replyListMap[v.ReplyCommentId] = append(replyListMap[v.ReplyCommentId], t)
+		}
+	}
+
+	// 查询精选留言相关的用户
+	var userOthers []*wx_user.WxUser
+	if len(userIds) > 0 {
+		userOthers, err = wx_user.GetByUserIds(userIds)
+		if err != nil {
+			errMsg = err.Error()
+			err = errors.New("查询精选留言用户出错")
+			return
+		}
+	}
+	usersMap := make(map[uint64]*wx_user.WxUser)
+	for _, v := range userOthers {
+		usersMap[v.UserID] = v
+	}
+	var list []*response.RespCommentItem
+	for _, v := range commentList {
+		tmp := new(response.RespCommentItem)
+		tmp.CommentId = v.CommentId
+		tmp.UserId = v.UserId
+		tmp.UserName = "匿名用户"+strconv.Itoa(int(3333+v.UserId))
+		tmp.UserImgUrl = utils.DEFAULT_HONGZE_USER_LOGO
+		if info, ok := usersMap[v.UserId]; ok && v.IsShowName == 1{
+			tmp.UserName = info.NickName
+			tmp.UserImgUrl = info.Headimgurl
+		}
+		tmp.Content = v.Content
+		tmp.IsHot = v.IsHot
+		tmp.IsTop = v.IsTop
+		tmp.HotTopTime = v.HotTopTime
+		tmp.CreateTime = v.CreateTime
+		tmp.IsShowName = v.IsShowName
+		if existList, ok := replyListMap[v.CommentId]; ok {
+			tmp.ReplyList = existList
+		}
+		list = append(list, tmp)
+	}
+	ret.List = list
+	if hotFlag {
+		ret.Paging = response.GetPaging(pageIndex, pageSize, int(total))
+	}
+	return
+}

+ 18 - 28
services/company/permission.go

@@ -8,6 +8,7 @@ import (
 	"hongze/hongze_yb/models/response"
 	"hongze/hongze_yb/models/tables/admin"
 	"hongze/hongze_yb/models/tables/chart_permission"
+	"hongze/hongze_yb/models/tables/chart_permission_first"
 	"hongze/hongze_yb/models/tables/company"
 	"hongze/hongze_yb/models/tables/company_product"
 	"hongze/hongze_yb/models/tables/company_report_permission"
@@ -655,17 +656,18 @@ func GetHomeFiccPermissions(user user.UserInfo) (ret response.PermissionFiccResp
 	}
 	permissionMap := make(map[uint64]bool)
 	permissionFirstMap := make(map[string]*response.PermissionFirstItem)
-	permissionFirstMap["宏观经济"] = &response.PermissionFirstItem{
-		Sort: 1001,
-	}
-	permissionFirstMap["化工产业"] = &response.PermissionFirstItem{
-		Sort: 1002,
-	}
-	permissionFirstMap["建材产业"] = &response.PermissionFirstItem{
-		Sort: 1003,
+
+	//查询首页展示的图标
+	permissionFirstList, err := chart_permission_first.GetIndexShowList()
+	if err != nil {
+		return
 	}
-	permissionFirstMap["有色产业"] = &response.PermissionFirstItem{
-		Sort: 1004,
+	for _, v := range permissionFirstList {
+		permissionFirstMap[v.ClassifyName] = &response.PermissionFirstItem{
+			Sort: v.YbIndexSort+1000,
+			YbIndexName: v.YbIndexName,
+			YbIndexIcon: v.YbIndexIcon,
+		}
 	}
 
 	for k, v := range permissionList {
@@ -700,26 +702,14 @@ func GetHomeFiccPermissions(user user.UserInfo) (ret response.PermissionFiccResp
 	}
 
 	var list response.PermissionFiccList
-	for k, v := range permissionFirstMap {
+	for _, v := range permissionFirstMap {
 		temp := new(response.PermissionFiccItem)
 		temp.Sort = v.Sort
-		temp.ClassifyName = k
-		if strings.Contains(temp.ClassifyName, "宏观") {
-			temp.ClassifyName = "宏观经济"
-			temp.SelectIconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_hongguan_select.png"
-			temp.IconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_hongguan.png"
-		} else if temp.ClassifyName == "化工产业" {
-			temp.ClassifyName = "化工"
-			temp.SelectIconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_huagong_select.png"
-			temp.IconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_huagong.png"
-		} else if temp.ClassifyName == "建材产业" {
-			temp.ClassifyName = "建材"
-			temp.SelectIconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_black_select.png"
-			temp.IconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_black.png"
-		} else if temp.ClassifyName == "有色产业" {
-			temp.ClassifyName = "有色"
-			temp.SelectIconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_youse_select.png"
-			temp.IconUrl = utils.ALIYUN_YBIMG_HOST + "ficc_icon_idx_youse.png"
+		temp.ClassifyName = v.YbIndexName
+		temp.IconUrl = v.YbIndexIcon
+		if len(temp.IconUrl) > 4 {
+			tmpIcon := temp.IconUrl[:len(temp.IconUrl)-4]
+			temp.SelectIconUrl = tmpIcon + "_select.png"
 		}
 		if len(v.List) > 0 {
 			temp.List = v.List

+ 130 - 0
services/like/like.go

@@ -0,0 +1,130 @@
+package like
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/request/like"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/yb_like"
+	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/user"
+	"time"
+)
+
+// 设置点赞
+func SetLike(user user.UserInfo, req like.ReqLike) (resp response.RespLike, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("SetLike: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	reportId := req.ReportId
+	reportChapterId := req.ReportChapterId
+
+	if req.SourceAgent == 0 {
+		err = errors.New("请输入点赞来源")
+		return
+	}
+	if req.ReportChapterId <=0 && req.ReportId <=0 && req.OldReportId <=0 && req.OldReportChapterId <=0{
+		err = errors.New("请输入报告ID")
+		return
+	}
+	if (req.ReportChapterId > 0 && req.ReportId <=0 ) || (req.OldReportChapterId > 0 && req.OldReportId <= 0){
+		err = errors.New("请输入报告ID")
+		return
+	}
+	// 判断是否有点赞权限
+	err, errMsg = services.CheckSimpleCompanyProduct(user)
+	if err != nil {
+		return
+	}
+	//处理老报告, 转化成新报告ID
+	if req.ReportChapterId <=0 && req.ReportId <=0 && (req.OldReportId >0 || req.OldReportChapterId > 0) {
+		reportId, reportChapterId, err, errMsg = services.GetReportIdReportChapterIdByOldReportId(uint64(req.OldReportId), uint64(req.OldReportChapterId))
+		if err != nil {
+			return
+		}
+	} else {
+		// 判断报告ID是否正确
+		err, errMsg = services.CheckReportExistByReportIdReportChapterId(reportId, reportChapterId)
+		if err != nil {
+			return
+		}
+	}
+
+	//查询用户对研报的点赞状态
+	var likeItem *yb_like.YbLike
+	if reportId > 0 {
+		likeItem, err = yb_like.GetLikeByUserIdAndReportId(user.UserID, reportId, reportChapterId)
+	} else {
+		likeItem, err = yb_like.GetLikeByUserIdAndOldReportId(user.UserID, req.OldReportId, req.OldReportChapterId)
+	}
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询用户点赞记录出错")
+		return
+	}
+	//如果未点赞则新增点赞记录
+	now :=  time.Now()
+	if likeItem.LikeId <= 0 {
+		likeItem = &yb_like.YbLike{
+			ReportId:          reportId,
+			ReportChapterId:   reportChapterId,
+			UserId:            user.UserID,
+			Enabled:         1,
+			CreateTime:     now,
+			ModifyTime:     now,
+			SourceAgent:    req.SourceAgent,
+			OldReportId:    req.OldReportId,
+			OldReportChapterId: req.OldReportChapterId,
+		}
+		err = likeItem.Create()
+		if err != nil {
+			errMsg = err.Error()
+			err = errors.New("新增点赞记录出错")
+			return
+		}
+	} else {
+		//如果已点赞则更新成取消点赞
+		if likeItem.Enabled == 1 {
+			updates := []string{"enabled", "modify_time"}
+			likeItem.Enabled = 0
+			likeItem.ModifyTime = now
+			err = likeItem.Update(updates)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("更新点赞记录出错")
+				return
+			}
+		} else {
+			//如果取消点赞则更新成已点赞
+			updates := []string{"enabled", "modify_time"}
+			likeItem.Enabled = 1
+			likeItem.ModifyTime = now
+			err = likeItem.Update(updates)
+			if err != nil {
+				errMsg = err.Error()
+				err = errors.New("更新点赞记录出错")
+				return
+			}
+		}
+	}
+	//查询总的点赞数
+	var likeNum int64
+	if reportId > 0 {
+		likeNum, err = yb_like.GetLikeNumByReportId(reportId, reportChapterId)
+	}else{
+		likeNum, err = yb_like.GetLikeNumByOldReportId(req.OldReportId, req.OldReportChapterId)
+	}
+
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询点赞数出错")
+		return
+	}
+	resp.LikeEnabled = likeItem.Enabled
+	resp.LikeNum = likeNum
+	return
+}

+ 159 - 0
services/message/message.go

@@ -0,0 +1,159 @@
+package message
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/request/message"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/yb_message"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"time"
+)
+
+// GetList 查询消息列表
+func GetList(user user.UserInfo, msgType, pageIndex, pageSize int) (ret response.RespMessageList, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("message GetList: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+
+	//校验入参
+	//查询消息列表
+	offset := (pageIndex - 1) * pageSize
+	msgList, err := yb_message.GetListByType(user.UserID, msgType, offset, pageSize)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询消息列表出错")
+		return
+	}
+
+	total, err := yb_message.GetListTotalByType(user.UserID, msgType)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询消息列表总数出错")
+		return
+	}
+
+	//处理列表返回值
+	var list []*response.RespMessageItem
+	for _, v := range msgList {
+		tmp := new(response.RespMessageItem)
+		tmp.MsgId = v.MsgId
+		tmp.IsRead = v.IsRead
+		tmp.UserId = v.UserId
+		tmp.Type = v.Type
+		tmp.CreateTime = v.CreateTime
+		tmp.ReportChapterId = v.ReportChapterId
+		tmp.ReportId = v.ReportId
+		tmp.OldReportId = v.OldReportId
+		tmp.OldReportChapterId = v.OldReportChapterId
+		tmp.ContentFirst = v.ContentFirst
+		tmp.ContentSecond = v.ContentSecond
+		tmp.Img = utils.DEFAULT_HONGZE_SYS_LOGO
+		list = append(list, tmp)
+	}
+	
+	ret.List = list
+	ret.Paging = response.GetPaging(pageIndex, pageSize, int(total))
+	return
+}
+
+// BatchRead 一键已读
+func BatchRead(user user.UserInfo, req message.ReqMessageBatch) (err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("message BatchRead: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+
+	//根据类型设置一键已读
+    err = yb_message.SetBatchRead(user.UserID, req.Type)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("一键已读设置失败")
+		return
+	}
+	return
+}
+
+// SingleRead 单条消息设置已读
+func SingleRead(user user.UserInfo, req message.ReqMessage) (err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("message SingleRead: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	if req.MsgId <=0 {
+		err = errors.New("请输入消息序号")
+		return
+	}
+	//查询当前消息
+	msgInfo, err := yb_message.GetMsgByMsgId(user.UserID, req.MsgId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询消息出错")
+		return
+	}
+	if msgInfo.MsgId <= 0 {
+		err = errors.New("消息不存在")
+		return
+	}
+	if msgInfo.IsRead == 1 {
+		return
+	}
+	msgInfo.IsRead = 1
+	msgInfo.ModifyTime = time.Now()
+	//根据类型设置一键已读
+	err = msgInfo.Update([]string{"is_read","modify_time"})
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("已读设置失败")
+		return
+	}
+	return
+}
+
+
+// SingleDelete 单条消息删除
+func SingleDelete(user user.UserInfo, req message.ReqMessage) (err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("message SingleDelete: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	if req.MsgId <=0 {
+		err = errors.New("请输入消息序号")
+		return
+	}
+	//查询当前消息
+	msgInfo, err := yb_message.GetMsgByMsgId(user.UserID, req.MsgId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询消息出错")
+		return
+	}
+	if msgInfo.MsgId <= 0 {
+		err = errors.New("消息不存在")
+		return
+	}
+	if msgInfo.Enabled == 0 {
+		return
+	}
+	msgInfo.Enabled = 0
+	msgInfo.ModifyTime = time.Now()
+	//根据类型设置一键已读
+	err = msgInfo.Update([]string{"enabled","modify_time"})
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("删除消息失败")
+		return
+	}
+	return
+}

+ 7 - 55
services/pc/classify.go

@@ -7,7 +7,6 @@ import (
 	"hongze/hongze_yb/models/response/pc"
 	"hongze/hongze_yb/models/tables/rddp/classify"
 	"hongze/hongze_yb/services/user"
-	"hongze/hongze_yb/utils"
 	"sort"
 )
 
@@ -31,62 +30,15 @@ func GetClassifyFirstList(user user.UserInfo) (list pc.ClassifyFirstList, err er
 		return
 	}
 
-	// 当前版本一级分类固定
-	classifyIconMap := map[string]string{
-		"晨报": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_blue.png",
-		"周报": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_blue.png",
-		"双周报": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_blue.png",
-		"月报": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_blue.png",
-		"草根调研": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"需求报告": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_green.png",
-		"宏观报告": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_green.png",
-		"日度点评": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"数据点评": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_green.png",
-		"碳市场价格周报": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_blue.png",
-		"行业调研": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"海外视角": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"百家谈": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"会议纪要": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_green.png",
-		"大事点评":  utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_orange.png",
-		"年报合集": utils.ALIYUN_YBIMG_HOST + "ficc_classify_bg_green.png",
+	classifyIconMap := make(map[string]string)
+	classifySortMap := make(map[string]int)
+	var names []string
+	for _, v := range classifyParents {
+		classifyIconMap[v.ClassifyName] = v.YbFiccPcIcon
+		classifySortMap[v.ClassifyName] = v.YbFiccSort
+		names = append(names, v.ClassifyName)
 	}
 
-	classifySortMap := map[string]int{
-		"晨报": 1,
-		"周报": 2,
-		"双周报": 3,
-		"月报": 4,
-		"草根调研": 5,
-		"需求报告": 6,
-		"宏观报告": 7,
-		"日度点评": 8,
-		"数据点评": 9,
-		"碳市场价格周报": 10,
-		"行业调研": 11,
-		"海外视角": 12,
-		"百家谈": 13,
-		"会议纪要": 14,
-		"大事点评":  15,
-		"年报合集": 16,
-	}
-	names := []string{
-		"晨报",
-		"周报",
-		"双周报",
-		"月报",
-		"草根调研",
-		"需求报告",
-		"宏观报告",
-		"日度点评",
-		"数据点评",
-		"碳市场价格周报",
-		"行业调研",
-		"海外视角",
-		"百家谈",
-		"会议纪要",
-		"大事点评",
-		"年报合集",
-	}
 	reportList,err := pc.GetLatestStage(names)
 	if err != nil {
 		errMsg = err.Error()

+ 7 - 39
services/report/classify.go

@@ -70,6 +70,7 @@ func GetClassListByClassifyId(user user.UserInfo, classifyIdFirst int) (list []*
 		temp.ClassifyIdSecond = item.Id
 		temp.ParentId = item.ParentId
 		temp.AuthorDescript = item.AuthorDescript
+		temp.Abstract = item.Abstract
 		temp.ReportAuthor = item.ReportAuthor
 		temp.HomeImgUrl = item.AvatarImgUrl	// 此处图片用二级分类的"头像"
 		temp.ClassifyNameSecond = item.ClassifyName
@@ -231,7 +232,7 @@ func GetClassifyReportList(user user.UserInfo, classifyIdSecond int, pageIndex,
 			if reportInfo.Abstract != "" {
 				reportItem.Abstract = "<div style=\"overflow: hidden;white-space: nowrap;text-overflow: ellipsis;\">" +reportInfo.Abstract+"</div>"
 			}
-			reportItem.Author = reportInfo.Author
+			reportItem.Author = classifyInfo.ReportAuthor
 			reportItem.ReportImgUrl = classifyInfo.AvatarImgUrl	// 此处图片用二级分类的"头像"
 			reportItem.VideoName = reportInfo.VideoName
 			reportItem.VideoPlaySeconds = reportInfo.VideoPlaySeconds
@@ -321,44 +322,11 @@ func GetClassifyFirstList(user user.UserInfo) (list response.ClassifyFirstList,
 		err = errors.New("分类不存在")
 		return
 	}
-
-	// 当前版本一级分类固定
-	classifyIconMap := map[string]string{
-		"晨报": utils.ALIYUN_YBIMG_HOST + "ficc_icon_day_128.png",
-		"周报": utils.ALIYUN_YBIMG_HOST + "ficc_icon_week_128.png",
-		"双周报": utils.ALIYUN_YBIMG_HOST + "ficc_icon_two_week_128.png",
-		"月报": utils.ALIYUN_YBIMG_HOST + "ficc_icon_month_128.png",
-		"草根调研": utils.ALIYUN_YBIMG_HOST + "ficc_icon_grassroots_128.png",
-		"需求报告": utils.ALIYUN_YBIMG_HOST + "ficc_icon_need_report_128.png",
-		"宏观报告": utils.ALIYUN_YBIMG_HOST + "ficc_icon_hongguan_128.png",
-		"日度点评": utils.ALIYUN_YBIMG_HOST + "ficc_icon_daily_comment_128.png",
-		"数据点评": utils.ALIYUN_YBIMG_HOST + "ficc_icon_data_128.png",
-		"碳市场价格周报": utils.ALIYUN_YBIMG_HOST + "ficc_icon_rcarbon_128.png",
-		"行业调研": utils.ALIYUN_YBIMG_HOST + "ficc_icon_research_128.png",
-		"海外视角": utils.ALIYUN_YBIMG_HOST + "ficc_icon_overseas_128.png",
-		"百家谈": utils.ALIYUN_YBIMG_HOST + "ficc_icon_family_128.png",
-		"会议纪要": utils.ALIYUN_YBIMG_HOST + "ficc_icon_meeting_128.png",
-		"大事点评":  utils.ALIYUN_YBIMG_HOST + "ficc_icon_big_thing_128.png",
-		"年报合集": utils.ALIYUN_YBIMG_HOST + "ficc_icon_year_collect_128.png",
-	}
-
-	classifySortMap := map[string]int{
-		"晨报": 1,
-		"周报": 2,
-		"双周报": 3,
-		"月报": 4,
-		"草根调研": 5,
-		"需求报告": 6,
-		"宏观报告": 7,
-		"日度点评": 8,
-		"数据点评": 9,
-		"碳市场价格周报": 10,
-		"行业调研": 11,
-		"海外视角": 12,
-		"百家谈": 13,
-		"会议纪要": 14,
-		"大事点评":  15,
-		"年报合集": 16,
+	classifyIconMap := make(map[string]string)
+	classifySortMap := make(map[string]int)
+	for _, v := range classifyParents {
+		classifyIconMap[v.ClassifyName] = v.YbFiccIcon
+		classifySortMap[v.ClassifyName] = v.YbFiccSort
 	}
 	for _, item := range classifyParents {
 		temp := new(response.ClassifyFirstListItem)

+ 11 - 4
services/report/report.go

@@ -19,10 +19,10 @@ import (
 	"hongze/hongze_yb/models/tables/rddp/report_chapter_ticker"
 	"hongze/hongze_yb/models/tables/report_chapter_type"
 	"hongze/hongze_yb/models/tables/report_chapter_type_permission"
+	"hongze/hongze_yb/services"
 	"hongze/hongze_yb/services/company"
 	elasticService "hongze/hongze_yb/services/elastic"
 	"hongze/hongze_yb/services/user"
-	"hongze/hongze_yb/task"
 	"hongze/hongze_yb/utils"
 	"html"
 	"sort"
@@ -342,7 +342,7 @@ func GetPurchaseDetail(permissionIds []int, userId uint64, classifyIdFirst int,
 	ret.Paging = response.GetPaging(pageIndex, pageSize, int(total))
 	// 执行一个协程任务,新增用户浏览记录
 	//_, tErr := BatchInsertReportView(weekReportIds, userId, classifyNameFirst, classifyIdSeconds)
-	task.Task(BatchInsertReportView, weekReportIds, userId, classifyNameFirst, classifyIdSeconds)
+	go BatchInsertReportView(userId, weekReportIds, classifyNameFirst, classifyIdSeconds)
 	/*if tErr != nil {
 		err = tErr
 		return
@@ -468,17 +468,24 @@ func GetReportDetail(userinfo user.UserInfo, reportId int) (reportDetail respons
 		}
 	}
 	//如果有权限则展示content
+	var likeNum int64
+	var likeEnabled int8
 	if authOk {
-		task.Task(AddViewRecord, userinfo, reportInfo.Id, reportInfo.ClassifyNameFirst, 0)
+		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)
 	}
+
 	//新增用户访问日志
-	task.Task(AddUserAccessRecord, userinfo, reportInfo.Id, reportInfo.ClassifyNameFirst, 0, authOk)
+	go AddUserAccessRecord(userinfo, reportInfo.Id, reportInfo.ClassifyNameFirst, 0, authOk)
 	reportDetail.ReportInfo = reportItem
 	reportDetail.ReportChapterList = reportTypeList
 	reportDetail.PermissionCheck = &permissionCheckInfo
 	reportDetail.AuthOk = authOk
+	reportDetail.LikeNum = likeNum
+	reportDetail.LikeEnabled = likeEnabled
 	return
 }
 

+ 10 - 4
services/report/report_chapter.go

@@ -11,9 +11,9 @@ import (
 	"hongze/hongze_yb/models/tables/rddp/report"
 	"hongze/hongze_yb/models/tables/rddp/report_chapter"
 	"hongze/hongze_yb/models/tables/report_chapter_type"
+	"hongze/hongze_yb/services"
 	"hongze/hongze_yb/services/company"
 	"hongze/hongze_yb/services/user"
-	"hongze/hongze_yb/task"
 	"hongze/hongze_yb/utils"
 	"html"
 	"sort"
@@ -258,6 +258,8 @@ func GetChapterDetail(user user.UserInfo, reportChapterId int) (reportChapterDet
 	reportChapterItem.Stage = reportChapter.Stage
 	reportChapterItem.ClassifyNameFirst = reportChapter.ClassifyNameFirst
 	reportChapterItem.ClassifyIdFirst = reportChapter.ClassifyIdFirst
+	var likeNum int64
+	var likeEnabled int8
 	if authOk {
 		reportChapterItem.Content = html.UnescapeString(reportChapter.Content)
 		reportChapterItem.VideoUrl = reportChapter.VideoUrl
@@ -267,17 +269,21 @@ func GetChapterDetail(user user.UserInfo, reportChapterId int) (reportChapterDet
 		}else{
 			chapterMenu, err = GetMenuChapter(reportInfo.Id, typeIds, reportInfo.ClassifyNameFirst, reportInfo.CreateTime)
 		}
-
-		task.Task(AddViewRecord, user, reportInfo.Id, reportInfo.ClassifyNameFirst, reportChapterId)
+		//查询点赞数
+		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)
 	}
-	task.Task(AddUserAccessRecord, user, reportInfo.Id, reportInfo.ClassifyNameFirst, reportChapterId, authOk)
+
+	go AddUserAccessRecord(user, reportInfo.Id, reportInfo.ClassifyNameFirst, reportChapterId, authOk)
 	reportChapterDetail = new(response.ReportChapterDetail)
 	reportChapterDetail.ReportChapterItem = reportChapterItem
 	reportChapterDetail.PermissionCheck = &permissionCheckInfo
 	reportChapterDetail.ReportChapterMenuList = chapterMenu
 	reportChapterDetail.AuthOk = authOk
+	reportChapterDetail.LikeNum = likeNum
+	reportChapterDetail.LikeEnabled = likeEnabled
 	return
 }
 

+ 1 - 7
services/report/report_view_log.go

@@ -52,19 +52,13 @@ func GetUnRead(classifyIdSeconds []int, userId uint64) (unReadItem map[string]in
 }
 
 // BatchInsertReportView 批量新增报告已读记录
-func BatchInsertReportView(params ...interface{}) {
+func BatchInsertReportView(userId uint64, weekReportIds []int, classifyNameFirst string, classifyIdSeconds []int) {
 	var err error
-	userId   := params[1].(uint64)
 	defer func() {
 		if err != nil {
 			global.LOG.Critical(fmt.Sprintf("Task BatchInsertReportView: userId=%d, err:%s, recover:%s", userId, err.Error(), recover()))
 		}
 	}()
-
-	weekReportIds := params[0]
-	classifyNameFirst := params[2]
-	classifyIdSeconds := params[3]
-
 	firstDay := "2022-01-01"
 	var newReports []*report.Report
 	pars := make([]interface{}, 0)

+ 2 - 13
services/report/report_view_record.go

@@ -1,7 +1,6 @@
 package report
 
 import (
-	"errors"
 	"fmt"
 	companyCache "hongze/hongze_yb/cache/company"
 	"hongze/hongze_yb/global"
@@ -10,23 +9,13 @@ import (
 	"time"
 )
 
-func AddViewRecord(params ...interface{}) {
+func AddViewRecord(userInfo user.UserInfo, reportId int, classifyName string, reportChapterId int) {
 	var err error
-	userInter  := params[0]
-	userInfo, ok := (userInter).(user.UserInfo)
-	if !ok {
-		err = errors.New("格式换转失败")
-		return
-	}
 	defer func() {
 		if err != nil {
-			global.LOG.Critical(fmt.Sprintf("Task BatchInsertReportView: userId=%d, err:%s", userInfo.UserID, err.Error()))
+			global.LOG.Critical(fmt.Sprintf("BatchInsertReportView: userId=%d, err:%s", userInfo.UserID, err.Error()))
 		}
 	}()
-
-	reportId := params[1].(int)
-	classifyName := params[2]
-	reportChapterId := params[3].(int)
 	companyInfo, err := companyCache.GetByCompanyId(userInfo.CompanyID)
 	if err != nil {
 		return

+ 2 - 13
services/report/user_access_record.go

@@ -1,7 +1,6 @@
 package report
 
 import (
-	"errors"
 	"fmt"
 	"hongze/hongze_yb/global"
 	"hongze/hongze_yb/models/tables/user_access_record"
@@ -10,24 +9,14 @@ import (
 )
 
 // AddUserAccessRecord 新增报告浏览记录
-func AddUserAccessRecord(params ...interface{}){
+func AddUserAccessRecord(userInfo user.UserInfo, reportId int, classifyName string, reportChapterId int, authOk bool){
 	var err error
-	userInter  := params[0]
-	userInfo, ok := (userInter).(user.UserInfo)
-	if !ok {
-		err = errors.New("格式换转失败")
-		return
-	}
 	defer func() {
 		if err != nil {
-			global.LOG.Critical(fmt.Sprintf("Task AddUserAccessRecord: userId=%d, err:%s", userInfo.UserID, err.Error()))
+			global.LOG.Critical(fmt.Sprintf("AddUserAccessRecord: userId=%d, err:%s", userInfo.UserID, err.Error()))
 		}
 	}()
-	reportId := params[1].(int)
 	if reportId > 0 {
-		classifyName := params[2]
-		reportChapterId := params[3].(int)
-		authOk := params[4].(bool)
 		record := new(user_access_record.UserAccessRecord)
 		record.Uid = int(userInfo.UserID)
 		record.Token = userInfo.LoginToken

+ 2 - 2
services/user/user.go

@@ -232,10 +232,10 @@ func GetFirstWxUserItemByUnionId(unionId string) (userInfo UserInfo, err error)
 func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.UserRecord) (userInfo UserInfo) {
 	wxUser.OpenID = userRecord.OpenID
 	wxUser.UnionID = userRecord.UnionID
-	wxUser.NickName = userRecord.NickName
+	//wxUser.NickName = userRecord.NickName
 	//wxUser.RealName = userRecord.RealName
 	//wxUser.BindAccount = userRecord.BindAccount
-	wxUser.Headimgurl = userRecord.Headimgurl
+	//wxUser.Headimgurl = userRecord.Headimgurl
 
 	wxUserJson, _ := json.Marshal(wxUser)
 	_ = json.Unmarshal(wxUserJson, &userInfo)

+ 77 - 0
services/wx_app/security/security.go

@@ -0,0 +1,77 @@
+package security
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/silenceper/wechat/v2/miniprogram"
+	"github.com/silenceper/wechat/v2/miniprogram/content"
+	"github.com/silenceper/wechat/v2/util"
+)
+
+
+// 检查一段文本是否含有违法违规内容。
+// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
+const SecurityMsgCheckUrl = "https://api.weixin.qq.com/wxa/msg_sec_check"
+
+type Security struct {
+	*content.Content
+}
+
+type MyMiniprogram struct {
+       *miniprogram.MiniProgram
+}
+
+func NewMyMiniprogram(miniprogram *miniprogram.MiniProgram) *MyMiniprogram {
+	return &MyMiniprogram{miniprogram}
+}
+
+type BodyContent struct {
+	Version       int8    `json:"version"`    // 接口版本号,2.0版本为固定值2
+	Openid        string  `json:"openid"`     // 用户的openid(用户需在近两小时访问过小程序)
+	Scene         int8    `json:"scene"`      // 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
+	Content       string  `json:"content"`    // 需检测的文本内容,文本字数的上限为2500字,需使用UTF-8编码
+	Nickname      string  `json:"nickname"`   // 用户昵称,需使用UTF-8编码
+	Title         string  `json:"title"`      // 文本标题,需使用UTF-8编码
+	Signature     string  `json:"signature"`  // 个性签名,该参数仅在资料类场景有效(scene=1),需使用UTF-8编码
+}
+
+func (s *MyMiniprogram) MsgSecCheckWithResult(bodyContent *BodyContent) (result Result, err error)  {
+	var accessToken string
+	accessToken, err = s.GetContentSecurity().GetAccessToken()
+	if err != nil {
+		return
+	}
+	uri := fmt.Sprintf("%s?access_token=%s", SecurityMsgCheckUrl, accessToken)
+	response, err := util.PostJSON(uri, bodyContent)
+	if err != nil {
+		return
+	}
+	return DecodeWithResult(response, "MsgSecCheck")
+}
+
+type Result struct {
+	Result *ResultBody
+}
+type ResultBody struct {
+	Suggest string  //建议,有risky、pass、review三种值
+	Label  int      //命中标签枚举值,100 正常;10001 广告;20001 时政;20002 色情;20003 辱骂;20006 违法犯罪;20008 欺诈;20012 低俗;20013 版权;21000 其他
+}
+
+func DecodeWithResult(response []byte, apiName string) (result Result, err error)  {
+	var commError util.CommonError
+	err = json.Unmarshal(response, &commError)
+	if err != nil {
+		return
+	}
+	if commError.ErrCode != 0 {
+		err = errors.New(fmt.Sprintf("%s Error , errcode=%d , errmsg=%s", apiName, commError.ErrCode, commError.ErrMsg))
+		return
+	}
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return
+	}
+	return
+}
+

+ 14 - 0
services/wx_app/wx_app.go

@@ -10,6 +10,7 @@ import (
 	"github.com/silenceper/wechat/v2/miniprogram/encryptor"
 	"github.com/silenceper/wechat/v2/miniprogram/qrcode"
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/services/wx_app/security"
 )
 
 //微信小程序配置信息
@@ -83,3 +84,16 @@ func GetSunCode(page, scene string) (resp []byte, err error) {
 	qr := wechatClient.GetQRCode()
 	return qr.GetWXACodeUnlimit(codePars)
 }
+
+// MsgSecCheck 检查一段文本是否含有违法违规内容。
+func MsgSecCheck(openid string,content string) (result security.Result, err error) {
+	wechatClient := GetWxApp()
+	myMiniprogram := security.NewMyMiniprogram(wechatClient)
+	bodyContent := &security.BodyContent{
+		Version: 2,
+		Content: content,
+		Openid: openid,
+		Scene: 2,
+	}
+	return myMiniprogram.MsgSecCheckWithResult(bodyContent)
+}

+ 174 - 0
services/yb_common.go

@@ -0,0 +1,174 @@
+package services
+
+import (
+	"errors"
+	"hongze/hongze_yb/models/tables/company_product"
+	"hongze/hongze_yb/models/tables/rddp/report"
+	"hongze/hongze_yb/models/tables/rddp/report_chapter"
+	"hongze/hongze_yb/models/tables/research_report_type"
+	"hongze/hongze_yb/models/tables/yb_like"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"strings"
+)
+
+// GetReportIdReportChapterIdByOldReportId 根据老报告的ID查询对应的新报告ID
+func GetReportIdReportChapterIdByOldReportId(oldReportId, oldReportChapterId uint64) (reportId int, reportChapterId int, err error, errMsg string)  {
+	var reportNew *report.Report
+	if oldReportChapterId >0 {
+		//查询章节详情,根据章节类型ID和老报告ID,根据老报告ID,查询新报告ID,根据新报告ID和type_id 找到新的章节ID
+		var oldReportChapter *research_report_type.ResearchReportTypeInfo
+		var reportChapterNew *report_chapter.ReportChapter
+		oldReportChapter, err = research_report_type.GetResearchReportTypeInfo(oldReportChapterId)
+		if err != nil {
+			errMsg = err.Error()
+			err = errors.New("找不到报告章节")
+			return
+		}
+		if  oldReportChapter == nil {
+			err = errors.New("找不到报告章节")
+			return
+		}
+		if oldReportId != oldReportChapter.ResearchReportID {
+			err = errors.New("报告ID和章节ID不一致")
+			return
+		}
+		//判断是否是晨报或者周报的章节ID,双周报的章节ID不记录
+		if oldReportChapter.TypeID == 0 {
+			err = errors.New("只允许传晨报和周报的章节ID")
+			return
+		}
+		reportNew, err = report.GetReportByOldReportId(oldReportChapter.ResearchReportID)
+		if err != nil {
+			errMsg = err.Error()
+			//err = errors.New("找不到新版报告")
+			return
+		}
+		if reportNew.Id <=0 {
+			//err = errors.New("找不到新版报告")
+			return
+		}
+		reportChapterNew, err = report_chapter.GetChapterByReportIdTypeId(reportNew.Id, oldReportChapter.TypeID)
+		if err != nil {
+			errMsg = err.Error()
+			return
+		}
+		if reportChapterNew.ReportChapterId <= 0 {
+			//err = errors.New("找不到新版章节")
+			return
+		}
+		reportId = reportNew.Id
+		reportChapterId = reportChapterNew.ReportChapterId
+		return
+	}else if oldReportId > 0 {
+		// 查询新报告ID
+		reportNew, err = report.GetReportByOldReportId(oldReportId)
+		if err != nil {
+			errMsg = err.Error()
+			//err = errors.New("找不到新版报告")
+			return
+		}
+		reportId = reportNew.Id
+        return
+	}
+	return
+}
+// CheckReportExistByReportIdReportChapterId 评论和点赞时,校验传入的报告ID是否正确
+func CheckReportExistByReportIdReportChapterId(reportId, reportChapterId int)(err error, errMsg string) {
+	reportInfo, err := report.GetByReportId(reportId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询报告出错")
+		return
+	}
+	if reportInfo.Id <=0  {
+		err = errors.New("报告不存在")
+		return
+	}
+
+	if (reportInfo.ClassifyNameFirst == "晨报" || reportInfo.ClassifyNameFirst == "周报") && reportChapterId <=0 {
+		err = errors.New("请输入报告章节ID")
+		return
+	}
+
+	if reportChapterId > 0 {
+		reportChapterInfo, tErr := report_chapter.GetTypeIdById(reportChapterId)
+		if tErr != nil {
+			errMsg = tErr.Error()
+			err = errors.New("查询章节失败")
+			return
+		}
+
+		if reportChapterInfo.ReportChapterId == 0 {
+			err = errors.New("章节不存在或者未发布")
+			return
+		}
+
+		if reportChapterInfo.ReportId != reportId {
+			err = errors.New("章节ID和报告ID不匹配")
+			return
+		}
+	}
+	return
+}
+
+// CheckSimpleCompanyProduct 校验用户是否FICC产品的已购或者试用状态
+func CheckSimpleCompanyProduct(userinfo user.UserInfo) (err error, errMsg string){
+	// 判断用户状态是否是正常和永续
+	var productAuthOk bool
+	companyProduct, err := company_product.GetByCompany2ProductId(userinfo.CompanyID, 1)
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	if err != nil {
+		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
+			}
+		}
+	}
+	if !productAuthOk {
+		err = errors.New("无权操作")
+		return
+	}
+	return
+}
+
+func GetReportLikeByReportIdOldReportId(userId uint64,reportId, reportChapterId int, oldReportId, oldReportChapterId int) (likeNum int64, likeEnabled int8, err error)  {
+	// 根据老报告找到新报告的ID
+	if reportId == 0 && oldReportId > 0{
+		reportId, reportChapterId, err, _ = GetReportIdReportChapterIdByOldReportId(uint64(oldReportId), uint64(oldReportChapterId))
+	}
+	//查询总的点赞数
+	if reportId > 0{
+		likeNum, err = yb_like.GetLikeNumByReportId(reportId, reportChapterId)
+	} else if oldReportId > 0{
+		likeNum, err = yb_like.GetLikeNumByOldReportId(oldReportId, oldReportChapterId)
+	}
+
+	if err != nil {
+		err = errors.New("查询点赞数出错")
+		return
+	}
+
+	//查询用户对研报的点赞状态
+	var likeItem *yb_like.YbLike
+	if reportId > 0 {
+		likeItem, err = yb_like.GetLikeByUserIdAndReportId(userId, reportId, reportChapterId)
+	} else {
+		likeItem, err = yb_like.GetLikeByUserIdAndOldReportId(userId, oldReportId, oldReportChapterId)
+	}
+	if err != nil {
+		err = errors.New("查询用户点赞记录出错")
+		return
+	}
+	likeEnabled = likeItem.Enabled
+	return
+}

+ 6 - 1
utils/constants.go

@@ -146,4 +146,9 @@ const (
 	USER_RECORD_PLATFORM_CYGX                 // 查研观向小程序
 	_
 	USER_RECORD_PLATFORM_YB // 研报小程序
-)
+)
+
+const (
+	DEFAULT_HONGZE_USER_LOGO = "https://hzstatic.hzinsights.com/static/icon/hzyb/default_avatar.png"      //个人中心默认头像、匿名用户留言默认头像
+	DEFAULT_HONGZE_SYS_LOGO  = "https://hzstatic.hzinsights.com/static/yb_wx/hongze_sys_default_head.png" //弘则官方默认头像
+)