Pārlūkot izejas kodu

Merge branch 'master' into yb/9.0_fix

hsun 2 gadi atpakaļ
vecāks
revīzija
db2617b740
32 mainītis faili ar 1798 papildinājumiem un 47 dzēšanām
  1. 135 0
      controller/community/comment.go
  2. 44 0
      controller/community/question.go
  3. 2 2
      controller/like/like.go
  4. 506 0
      logic/yb_community_question/yb_community_question_comment.go
  5. 141 0
      logic/yb_community_question/yb_community_question_like_tease.go
  6. 9 9
      models/request/comment/comment.go
  7. 21 0
      models/request/community.go
  8. 14 14
      models/response/comment.go
  9. 45 1
      models/response/community.go
  10. 6 1
      models/tables/admin/query.go
  11. 67 0
      models/tables/company_approval_message/company_approval_message.go
  12. 8 0
      models/tables/company_approval_message/create.go
  13. 1 0
      models/tables/company_approval_message/query.go
  14. 17 0
      models/tables/company_approval_message/update.go
  15. 18 0
      models/tables/yb_comment_anonymous_user/create.go
  16. 15 0
      models/tables/yb_comment_anonymous_user/query.go
  17. 25 0
      models/tables/yb_comment_anonymous_user/yb_comment_anonymous_user.go
  18. 8 0
      models/tables/yb_community_question_comment/create.go
  19. 119 0
      models/tables/yb_community_question_comment/query.go
  20. 40 0
      models/tables/yb_community_question_comment/update.go
  21. 70 0
      models/tables/yb_community_question_comment/yb_community_question_comment.go
  22. 8 0
      models/tables/yb_community_question_like_tease/create.go
  23. 72 0
      models/tables/yb_community_question_like_tease/query.go
  24. 9 0
      models/tables/yb_community_question_like_tease/update.go
  25. 43 0
      models/tables/yb_community_question_like_tease/yb_community_question_like_tease.go
  26. 13 2
      routers/community.go
  27. 121 17
      services/community/question.go
  28. 4 0
      services/company/permission.go
  29. 80 0
      services/company_approval_message/company_approval_message.go
  30. 123 1
      services/wechat/template_msg.go
  31. 9 0
      services/wechat/wechat.go
  32. 5 0
      utils/constants.go

+ 135 - 0
controller/community/comment.go

@@ -0,0 +1,135 @@
+package community
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/logic/yb_community_question"
+	"hongze/hongze_yb/models/request"
+	responseModel "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/services"
+	userService "hongze/hongze_yb/services/user"
+	"strconv"
+)
+
+// Comment 发布留言
+func Comment(c *gin.Context) {
+	var req request.ReqComment
+	if c.ShouldBind(&req) != nil {
+		response.Fail("入参错误", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+
+	req.IsShowName = 0
+	if userInfo.NickName != `` { //非空串时为实名
+		req.IsShowName = 1
+	}
+	ybCommunityQuestionComment, err, errMsg := yb_community_question.Comment(userInfo, req.CommunityQuestionID, req.Content, req.SourceAgent, req.IsShowName)
+	if err != nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+	response.OkData("留言成功", responseModel.RespCommunityQuestionCommentAdd{
+		CommunityQuestionCommentID: ybCommunityQuestionComment.CommunityQuestionCommentID,
+	}, c)
+	return
+}
+
+// DeleteComment 删除留言
+func DeleteComment(c *gin.Context) {
+	var req *request.ReqDel
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+	err, errMsg := yb_community_question.Delete(userInfo, req.CommunityQuestionCommentID)
+	if err != nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+	response.Ok("删除留言成功", c)
+	return
+}
+
+// HotList 获取精选留言
+func HotList(c *gin.Context) {
+	communityQuestionIDStr := c.DefaultQuery("community_question_id", "")
+	communityQuestionID, err := strconv.Atoi(communityQuestionIDStr)
+	if err != nil {
+		response.Fail("问答id异常", c)
+		return
+	}
+	userinfo := userService.GetInfoByClaims(c)
+	page := services.GetCurrPageByClaims(c)
+	pageSize := services.GetPageSizeByClaims(c)
+
+	list, hotTotal, myTotal, err, errMsg := yb_community_question.List(userinfo.UserID, communityQuestionID, true, page, pageSize)
+	if err != nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", responseModel.RespCommunityQuestionCommentList{
+		List:     list,
+		Paging:   responseModel.GetPaging(page, pageSize, int(hotTotal)),
+		HotTotal: hotTotal,
+		MyTotal:  myTotal,
+	}, c)
+
+	return
+}
+
+// MyList 获取我的留言
+func MyList(c *gin.Context) {
+	communityQuestionIDStr := c.DefaultQuery("community_question_id", "")
+	communityQuestionID, err := strconv.Atoi(communityQuestionIDStr)
+	if err != nil {
+		response.Fail("问答id异常", c)
+		return
+	}
+	userinfo := userService.GetInfoByClaims(c)
+	page := services.GetCurrPageByClaims(c)
+	pageSize := services.GetPageSizeByClaims(c)
+
+	list, hotTotal, myTotal, err, errMsg := yb_community_question.MyList(userinfo.UserID, communityQuestionID, page, pageSize)
+	if err != nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", responseModel.RespCommunityQuestionCommentList{
+		List:     list,
+		Paging:   responseModel.GetPaging(page, pageSize, int(myTotal)),
+		HotTotal: hotTotal,
+		MyTotal:  myTotal,
+	}, c)
+	return
+}
+
+// GetNeedCommentAnonymousUserTips 获取是否 弹出让去设置头像 的提示框
+func GetNeedCommentAnonymousUserTips(c *gin.Context) {
+	userinfo := userService.GetInfoByClaims(c)
+
+	// true 不弹框,false弹框
+	if userinfo.NickName != `` {
+		response.OkData("获取成功", true, c)
+		return
+	}
+	ok, err := yb_community_question.GetNeedCommentAnonymousUserTips(userinfo.UserID)
+	if err != nil {
+		response.FailMsg("获取失败", err.Error(), c)
+		return
+	}
+
+	response.OkData("获取成功", ok, c)
+}
+
+// SetCommentAnonymousUserTips 设置不再提示 弹出让去设置头像 的提示框
+func SetCommentAnonymousUserTips(c *gin.Context) {
+	userinfo := userService.GetInfoByClaims(c)
+	err := yb_community_question.SetYbCommentAnonymousUserTips(userinfo.UserID)
+	if err != nil {
+		response.FailMsg("设置失败", err.Error(), c)
+		return
+	}
+	response.Ok("设置成功", c)
+}

+ 44 - 0
controller/community/question.go

@@ -5,11 +5,15 @@ import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/logic/yb_community_question"
 	"hongze/hongze_yb/models/request"
+
 	respond "hongze/hongze_yb/models/response"
+	responseModel "hongze/hongze_yb/models/response"
 	"hongze/hongze_yb/services"
 	"hongze/hongze_yb/services/community"
 	"hongze/hongze_yb/services/user"
+	userService "hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/services/wx_app"
 	"hongze/hongze_yb/utils"
 	"io/ioutil"
@@ -48,6 +52,21 @@ func QuestionList(c *gin.Context) {
 		response.FailMsg("获取失败", "QuestionList ErrMsg:"+err.Error(), c)
 		return
 	}
+
+	// 点赞/吐槽数据
+	err = yb_community_question.HandleLikeOrTeaseByCommunityQuestionItemList(userinfo.UserID, list)
+	if err != nil {
+		response.FailMsg("获取失败", "QuestionList ErrMsg:"+err.Error(), c)
+		return
+	}
+
+	// 评论数据
+	err = yb_community_question.HandleCommentByCommunityQuestionItemList(userinfo.UserID, list)
+	if err != nil {
+		response.FailMsg("获取失败", "QuestionList ErrMsg:"+err.Error(), c)
+		return
+	}
+
 	response.OkData("获取成功", list, c)
 }
 
@@ -324,3 +343,28 @@ func AddAudioLog(c *gin.Context) {
 	}
 	response.Ok("操作成功", c)
 }
+
+// SetLikeOrTease 问答点赞/吐槽设置
+func SetLikeOrTease(c *gin.Context) {
+	var req request.ReqCommunityQuestionLikeTease
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	userinfo := userService.GetInfoByClaims(c)
+
+	communityQuestionLikeTease, likeNum, teaseNum, err, errMsg := yb_community_question.SetLikeOrTease(userinfo.UserID, req.CommunityQuestionId, req.OpType, req.Enable, req.SourceAgent)
+	if err != nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+
+	response.OkData("操作成功", responseModel.RespCommunityQuestionLikeTease{
+		LikeTotal:  likeNum,
+		TeaseTotal: teaseNum,
+		OpType:     communityQuestionLikeTease.OpType,
+		Enabled:    communityQuestionLikeTease.Enabled,
+	}, c)
+
+	return
+}

+ 2 - 2
controller/like/like.go

@@ -9,7 +9,7 @@ import (
 )
 
 // SetLike 点赞设置
-func SetLike(c *gin.Context)  {
+func SetLike(c *gin.Context) {
 	var req like.ReqLike
 	if c.ShouldBind(&req) != nil {
 		response.Fail("参数异常", c)
@@ -22,6 +22,6 @@ func SetLike(c *gin.Context)  {
 		response.Fail(err.Error(), c)
 		return
 	}
-	response.OkData("操作成功", data, c )
+	response.OkData("操作成功", data, c)
 	return
 }

+ 506 - 0
logic/yb_community_question/yb_community_question_comment.go

@@ -0,0 +1,506 @@
+package yb_community_question
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/admin"
+	"hongze/hongze_yb/models/tables/company"
+	"hongze/hongze_yb/models/tables/company_product"
+	"hongze/hongze_yb/models/tables/wx_user"
+	"hongze/hongze_yb/models/tables/yb_comment_anonymous_user"
+	"hongze/hongze_yb/models/tables/yb_community_question"
+	"hongze/hongze_yb/models/tables/yb_community_question_comment"
+	"hongze/hongze_yb/services/alarm_msg"
+	"hongze/hongze_yb/services/company_approval_message"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/services/wechat"
+	"hongze/hongze_yb/services/wx_app"
+	"hongze/hongze_yb/utils"
+	"strconv"
+	"time"
+)
+
+// Comment 发布留言
+func Comment(user user.UserInfo, communityQuestionID uint32, content string, sourceAgent, isShowName int8) (ybCommunityQuestionComment *yb_community_question_comment.YbCommunityQuestionComment, err error, errMsg string) {
+	errMsg = "发布留言失败"
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("yb_community_question Comment: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	//校验请求入参
+	if isShowName != 0 && isShowName != 1 {
+		errMsg = "匿名设置出错"
+		err = errors.New(errMsg)
+		return
+	}
+	if content == "" {
+		errMsg = "请输入留言内容"
+		err = errors.New(errMsg)
+		return
+	}
+	if sourceAgent == 0 {
+		errMsg = "请输入留言来源"
+		err = errors.New(errMsg)
+		return
+	}
+	if communityQuestionID <= 0 {
+		errMsg = "请输入问答ID"
+		err = errors.New(errMsg)
+		return
+	}
+	// 敏感词过滤
+	if user.RecordInfo.OpenID != "" && user.RecordInfo.CreatePlatform == 6 { //只有小程序的用户才能走敏感词过滤接口
+		checkResult, tErr := wx_app.MsgSecCheck(user.RecordInfo.OpenID, 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
+				}
+			}
+		}
+	}
+
+	userName := "匿名用户" + strconv.Itoa(int(3333+user.UserID))
+	if user.RealName != `` {
+		userName = user.RealName
+	}
+	//新增留言
+	now := time.Now()
+	ybCommunityQuestionComment = &yb_community_question_comment.YbCommunityQuestionComment{
+		//CommunityQuestionCommentID: 0,
+		CommunityQuestionID: communityQuestionID,
+		UserID:              user.UserID,
+		RealName:            userName,
+		Content:             content,
+		//ReplyCommentID:             0,
+		//IsTop:                      0,
+		//IsHot:                      0,
+		//HotTopTime:                 time.Time{},
+		Type:        1,
+		Enabled:     1,
+		IsShowName:  isShowName,
+		SourceAgent: sourceAgent,
+		//TopTime:                    time.Time{},
+		//HotTime:                    time.Time{},
+		ModifyTime: now,
+		CreateTime: now,
+	}
+	err = ybCommunityQuestionComment.Create()
+	if err != nil {
+		errMsg = "新增留言失败"
+		return
+	}
+
+	// 用户评论完后发送消息给管理员
+	go messageToAdmin(user, ybCommunityQuestionComment)
+	return
+}
+
+// Delete 删除留言
+func Delete(user user.UserInfo, communityQuestionCommentID uint64) (err error, errMsg string) {
+	errMsg = `删除留言失败`
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("comment Delete: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	if communityQuestionCommentID <= 0 {
+		errMsg = `请输入留言ID`
+		err = errors.New(errMsg)
+		return
+	}
+	//校验请求入参
+	communityQuestionCommentInfo, err := yb_community_question_comment.GetByCommunityQuestionCommentId(communityQuestionCommentID)
+	if err != nil {
+		errMsg = `查询留言出错`
+		return
+	}
+	if communityQuestionCommentInfo.CommunityQuestionCommentID <= 0 {
+		errMsg = `留言不存在`
+		err = errors.New(errMsg)
+		return
+	}
+	if communityQuestionCommentInfo.UserID != user.UserID {
+		errMsg = `不允许删除他人的留言`
+		err = errors.New(errMsg)
+		return
+	}
+	if communityQuestionCommentInfo.Type != 1 {
+		errMsg = `不允许删除回复`
+		err = errors.New(errMsg)
+		return
+	}
+	if communityQuestionCommentInfo.Enabled == 0 {
+		return
+	}
+	err = yb_community_question_comment.Delete(user.UserID, communityQuestionCommentInfo.CommunityQuestionCommentID)
+	if err != nil {
+		errMsg = `删除留言出错`
+		return
+	}
+
+	go afterDelete(communityQuestionCommentInfo)
+	return
+}
+
+// MyList 我的留言列表
+func MyList(userId uint64, communityQuestionID int, page, pageSize int) (list []*response.RespCommunityQuestionCommentItem, hotTotal, myTotal int64, err error, errMsg string) {
+	list, hotTotal, myTotal, err, errMsg = List(userId, communityQuestionID, false, page, pageSize)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// List 查询精选留言列表或我的留言列表
+func List(userId uint64, communityQuestionID int, hotFlag bool, page, pageSize int) (list []*response.RespCommunityQuestionCommentItem, hotTotal, myTotal int64, err error, errMsg string) {
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("comment List: userId=%d, err:%s, errMsg:%s", userId, err.Error(), errMsg))
+		}
+	}()
+	list = make([]*response.RespCommunityQuestionCommentItem, 0)
+
+	if communityQuestionID <= 0 {
+		err = errors.New("请输入问答ID")
+		return
+	}
+
+	//精选留言数
+	hotTotal, err = yb_community_question_comment.GetHotListTotalByCommunityQuestionID(communityQuestionID)
+	if err != nil {
+		errMsg = `查询精选留言总数出错`
+		return
+	}
+
+	// 我的留言数
+	myTotal, err = yb_community_question_comment.GetListTotalByUserIdCommunityQuestionID(userId, communityQuestionID)
+	if err != nil {
+		errMsg = `查询我的留言总数出错`
+		return
+	}
+
+	var commentList []*yb_community_question_comment.YbCommunityQuestionComment
+	//查询精选留言
+	if hotFlag {
+		commentList, err = yb_community_question_comment.GetHotListByCommunityQuestionID(communityQuestionID, (page-1)*pageSize, pageSize)
+		if err != nil {
+			errMsg = `查询精选留言列表出错`
+			return
+		}
+
+	} else {
+		//查询个人留言
+		commentList, err = yb_community_question_comment.GetListByUserIdCommunityQuestionID(userId, communityQuestionID)
+		if err != nil {
+			errMsg = `查询我的留言列表出错`
+			return
+		}
+	}
+
+	var commentIds []uint64
+	var userIds []uint64
+	for _, v := range commentList {
+		commentIds = append(commentIds, v.CommunityQuestionCommentID)
+		userIds = append(userIds, v.UserID)
+	}
+
+	// 查询所有的回复列表
+	//{
+	//	replyListMap := make(map[uint64][]*response.ReplyItem)
+	//	if len(commentIds) > 0 {
+	//		replyList, tErr := yb_community_question_comment.GetReplyListByReplyCommentId(commentIds)
+	//		if tErr != nil {
+	//			errMsg = tErr.Error()
+	//			err = errors.New("查询回复出错")
+	//			return
+	//		}
+	//		for _, v := range replyList {
+	//			t := new(response.ReplyItem)
+	//			t.CommentId = v.CommunityQuestionCommentID
+	//			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
+	}
+	for _, v := range commentList {
+		tmp := &response.RespCommunityQuestionCommentItem{
+			CommunityQuestionCommentID: v.CommunityQuestionCommentID,
+			UserId:                     v.UserID,
+			Content:                    v.Content,
+			IsTop:                      v.IsTop,
+			IsHot:                      v.IsHot,
+			HotTopTime:                 v.HotTopTime,
+			IsShowName:                 v.IsShowName,
+			UserName:                   "匿名用户" + strconv.Itoa(int(3333+v.UserID)),
+			UserImgUrl:                 utils.DEFAULT_HONGZE_USER_LOGO,
+			CreateTime:                 v.CreateTime,
+			ReplyList:                  nil,
+		}
+		if info, ok := usersMap[v.UserID]; ok && v.IsShowName == 1 {
+			tmp.UserName = info.NickName
+			tmp.UserImgUrl = info.Headimgurl
+		}
+		//if existList, ok := replyListMap[v.CommentId]; ok {
+		//	tmp.ReplyList = existList
+		//}
+		list = append(list, tmp)
+	}
+	return
+}
+
+// GetNeedCommentAnonymousUserTips 获取是否 弹出让去设置头像 的提示框
+func GetNeedCommentAnonymousUserTips(userId uint64) (ok bool, err error) {
+	ybCommentAnonymousUser, err := yb_comment_anonymous_user.GetByUserId(userId)
+	if err != nil {
+		return
+	}
+	//如果能找到,那么认为是有设置过匿名评论,那么不需要需要弹框提示
+	if ybCommentAnonymousUser.UserID > 0 {
+		ok = true
+	}
+	return
+}
+
+// SetYbCommentAnonymousUserTips 设置不再提示 弹出让去设置头像 的提示框
+func SetYbCommentAnonymousUserTips(userId uint64) (err error) {
+	ybCommentAnonymousUser, err := yb_comment_anonymous_user.GetByUserId(userId)
+	if err != nil {
+		return
+	}
+	//如果找不到,那么认为是第一次评论,那么需要弹框提示
+	if ybCommentAnonymousUser.UserID <= 0 {
+		//ybCommentAnonymousUser = &yb_comment_anonymous_user.YbCommentAnonymousUser{
+		//	UserID:     userId,
+		//	CreateTime: time.Now(),
+		//}
+		//err = ybCommentAnonymousUser.Create()
+		err = yb_comment_anonymous_user.CreateBySql(userId, time.Now())
+	}
+	return
+}
+
+// HandleCommentByCommunityQuestionItemList 问答 评论 数据
+func HandleCommentByCommunityQuestionItemList(userId uint64, questionList []*response.CommunityQuestionItem) (err error) {
+	listLen := len(questionList)
+	if listLen == 0 {
+		return
+	}
+	idArr := make([]uint32, 0)
+	idMap := make(map[uint32]int)
+
+	userIds := []uint64{userId} //所有的评论人
+
+	for i := 0; i < listLen; i++ {
+		idArr = append(idArr, uint32(questionList[i].CommunityQuestionID))
+		idMap[uint32(questionList[i].CommunityQuestionID)] = 1
+	}
+
+	//精选评论数据、我的评论数据
+	ybCommunityQuestionCommentMap := make(map[uint32]*yb_community_question_comment.YbCommunityQuestionComment)
+
+	//获取精选评论数据
+	hotList, err := yb_community_question_comment.GetLastHotListByCommunityQuestionIds(idArr)
+	if err != nil {
+		return
+	}
+	for _, v := range hotList {
+		ybCommunityQuestionCommentMap[v.CommunityQuestionID] = v
+		delete(idMap, v.CommunityQuestionID)
+
+		//评论人id
+		userIds = append(userIds, v.UserID)
+	}
+
+	//需要查询的我的问答的评论
+	myIdArr := make([]uint32, 0)
+	for id := range idMap {
+		myIdArr = append(myIdArr, id)
+	}
+
+	//获取我的评论数据
+	myList, err := yb_community_question_comment.GetLastMyListByCommunityQuestionIds(userId, myIdArr)
+	if err != nil {
+		return
+	}
+	for _, v := range myList {
+		ybCommunityQuestionCommentMap[v.CommunityQuestionID] = v
+	}
+
+	// 获取留言汇总数
+	numCommentMap := make(map[uint32]int)
+	numCommentList, err := yb_community_question_comment.GetNumCommentByCommunityQuestionIds(idArr, userId)
+	if err != nil {
+		return
+	}
+	for _, v := range numCommentList {
+		numCommentMap[v.CommunityQuestionID] = v.Total
+	}
+
+	var userOthers []*wx_user.WxUser
+	if len(userIds) > 0 {
+		userOthers, err = wx_user.GetByUserIds(userIds)
+		if err != nil {
+			err = errors.New("查询精选留言用户出错")
+			return
+		}
+	}
+	usersMap := make(map[uint64]*wx_user.WxUser)
+	for _, v := range userOthers {
+		usersMap[v.UserID] = v
+	}
+
+	for _, v := range questionList {
+		//评论汇总数
+		if tmpTotal, ok := numCommentMap[uint32(v.CommunityQuestionID)]; ok {
+			v.CommentTotal = tmpTotal
+		}
+
+		//最近一条 精选/我的 评论
+		if ybCommunityQuestionCommentInfo, ok := ybCommunityQuestionCommentMap[uint32(v.CommunityQuestionID)]; ok {
+			v.Comment = ybCommunityQuestionCommentInfo.Content
+			v.CommentUserName = "匿名用户" + strconv.Itoa(int(3333+ybCommunityQuestionCommentInfo.UserID))
+			if info, ok := usersMap[ybCommunityQuestionCommentInfo.UserID]; ok && ybCommunityQuestionCommentInfo.IsShowName == 1 {
+				v.CommentUserName = info.NickName
+				//v.UserImgUrl = info.Headimgurl
+			}
+		}
+	}
+	return
+}
+
+// messageToAdmin 添加站内消息
+func messageToAdmin(wxUser user.UserInfo, communityQuestionComment *yb_community_question_comment.YbCommunityQuestionComment) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增问答评论信息完成后,发送消息给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+
+	//因为产品说只要给沛总发送信息,那么没办法咯,只去获取沛总的信息 2022-07-19 11:29:16
+	vWangInfo, err := admin.GetVWangInfo()
+	if err != nil {
+		return
+	}
+	//站内消息
+	go systemMessageToAdmin(*vWangInfo, wxUser, communityQuestionComment)
+	//微信模板消息
+	go wxMessageToAdmin(*vWangInfo, communityQuestionComment)
+
+	return
+}
+
+// systemMessageToAdmin 系统消息消息通知管理员
+func systemMessageToAdmin(adminInfo admin.Admin, wxUser user.UserInfo, communityQuestionComment *yb_community_question_comment.YbCommunityQuestionComment) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增问答评论信息完成后,站内评论信息发送给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+	// 接收人的admin_id
+	receiveUserId := int(adminInfo.AdminID)
+
+	var msgType, sourceType, approvalStatus int8
+	msgType = company_approval_message.CompanyApprovalMessageMessageTypeByApply
+	sourceType = company_approval_message.CompanyApprovalMessageSourceTypeByQuestionComment
+	approvalStatus = company_approval_message.CompanyApprovalMessageApprovalStatusByPending
+
+	companyInfo, err := company.GetByCompanyId(wxUser.CompanyID)
+	if err != nil {
+		return
+	}
+
+	productId := 1
+	companyProductInfo, err := company_product.GetByCompany2ProductId(wxUser.CompanyID, int64(productId))
+	if err != nil {
+		return
+	}
+
+	companyName := companyInfo.CompanyName
+	remark := `您有新的问答评论待查阅`
+	content := `您有新的问答评论待查阅`
+
+	// 获取评论对应的问答信息
+	communityQuestion, err := yb_community_question.GetItemById(int(communityQuestionComment.CommunityQuestionID))
+	if err != nil {
+		err = errors.New("获取评论对应的问答失败,err:" + err.Error())
+	}
+	messageInfo := company_approval_message.MessageInfo{
+		CompanyName:          companyInfo.CompanyName,
+		ProductId:            productId,
+		CompanyProductStatus: companyProductInfo.Status,
+		Title:                communityQuestionComment.Content,
+		Content:              communityQuestion.QuestionContent,
+		UserId:               wxUser.UserID,
+		UserName:             communityQuestionComment.RealName,
+		CreateTime:           communityQuestionComment.CreateTime,
+	}
+	//客户添加消息
+	err = company_approval_message.AddCompanyApprovalMessage(utils.AdminId, receiveUserId, int(wxUser.CompanyID), int(communityQuestionComment.CommunityQuestionCommentID), msgType, sourceType, approvalStatus, companyName, remark, content, messageInfo)
+	return
+}
+
+// wxMessageToAdmin 微信模板消息通知管理员
+func wxMessageToAdmin(adminInfo admin.Admin, communityQuestionComment *yb_community_question_comment.YbCommunityQuestionComment) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增问答评论信息完成后,微信模板消息发送给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+
+	if global.CONFIG.Serve.RunMode == "debug" {
+		adminInfo.Mobile = `18221983795`
+	}
+	wxUser, err := wx_user.GetByMobile(adminInfo.Mobile)
+	if err != nil {
+		return
+	}
+
+	err = wechat.SendQuestionCommentToAdmin(int(communityQuestionComment.CommunityQuestionCommentID), int(wxUser.UserID), communityQuestionComment.Content)
+	return
+}
+
+// 删除评论后的逻辑处理
+func afterDelete(communityQuestionComment *yb_community_question_comment.YbCommunityQuestionComment) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("问答评论信息删除后,标记站内消息失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+	err = company_approval_message.CancelCompanyApprovalMessage(int(communityQuestionComment.CommunityQuestionCommentID), company_approval_message.CompanyApprovalMessageSourceTypeByQuestionComment)
+	return
+}

+ 141 - 0
logic/yb_community_question/yb_community_question_like_tease.go

@@ -0,0 +1,141 @@
+package yb_community_question
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/yb_community_question_like_tease"
+	"time"
+)
+
+// SetLikeOrTease 用户对问答进行(取消)点赞或(取消)吐槽
+func SetLikeOrTease(userId uint64, communityQuestionId uint32, opType, enable, sourceAgent int8) (ybCommunityQuestionLikeTease *yb_community_question_like_tease.YbCommunityQuestionLikeTease, likeNum, teaseNum int64, err error, errMsg string) {
+	//user.UserID
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("SetLike: userId=%d, err:%s, errMsg:%s", userId, err.Error(), errMsg))
+		}
+	}()
+
+	if sourceAgent == 0 {
+		err = errors.New("请输入来源")
+		return
+	}
+	if communityQuestionId <= 0 {
+		err = errors.New("请输入问答ID")
+		return
+	}
+	// 判断是否有点赞权限(不需要权限校验,先保留,有需要后续再说)
+	//err, errMsg = services.CheckSimpleCompanyProduct(user)
+	//if err != nil {
+	//	return
+	//}
+
+	//查询用户对问答的点赞/吐槽状态
+	ybCommunityQuestionLikeTease, err = yb_community_question_like_tease.GetByUserIdAndCommunityQuestionId(userId, communityQuestionId)
+	if err != nil {
+		errMsg = "查询点赞/吐槽记录出错"
+		return
+	}
+	//如果未点赞则新增点赞记录
+	now := time.Now()
+	if ybCommunityQuestionLikeTease.CommunityQuestionLikeTeaseID <= 0 {
+		ybCommunityQuestionLikeTease = &yb_community_question_like_tease.YbCommunityQuestionLikeTease{
+			//CommunityQuestionLikeTeaseID: 0,
+			UserID:              userId,
+			OpType:              opType,
+			Enabled:             1,
+			CreateTime:          now,
+			ModifyTime:          now,
+			CommunityQuestionID: communityQuestionId,
+			SourceAgent:         sourceAgent,
+		}
+		err = ybCommunityQuestionLikeTease.Create()
+		if err != nil {
+			errMsg = err.Error()
+			err = errors.New("新增点赞/吐槽记录出错")
+			return
+		}
+	} else {
+		ybCommunityQuestionLikeTease.OpType = opType
+		ybCommunityQuestionLikeTease.Enabled = enable
+		ybCommunityQuestionLikeTease.SourceAgent = sourceAgent
+		ybCommunityQuestionLikeTease.ModifyTime = now
+		updates := []string{"op_type", "enabled", "source_agent", "modify_time"}
+		err = ybCommunityQuestionLikeTease.Update(updates)
+		if err != nil {
+			errMsg = "更新点赞记录出错"
+			return
+		}
+	}
+	//查询总的点赞数
+	likeNum, err = yb_community_question_like_tease.GetLikeNumByCommunityQuestionId(communityQuestionId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询点赞数出错")
+	}
+	teaseNum, err = yb_community_question_like_tease.GetTeaseNumByCommunityQuestionId(communityQuestionId)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询吐槽数出错")
+	}
+	return
+}
+
+// HandleLikeOrTeaseByCommunityQuestionItemList 问答 点赞/吐槽 数据
+func HandleLikeOrTeaseByCommunityQuestionItemList(userId uint64, questionList []*response.CommunityQuestionItem) (err error) {
+	listLen := len(questionList)
+	if listLen == 0 {
+		return
+	}
+	idArr := make([]uint32, 0)
+	for i := 0; i < listLen; i++ {
+		idArr = append(idArr, uint32(questionList[i].CommunityQuestionID))
+	}
+
+	// 获取点赞和吐槽数据
+	ybCommunityQuestionLikeTeaseMap := make(map[uint32]*yb_community_question_like_tease.YbCommunityQuestionLikeTease)
+	ybCommunityQuestionLikeTeaseList, err := yb_community_question_like_tease.GetByUserIdAndCommunityQuestionIds(userId, idArr)
+	if err != nil {
+		return
+	}
+	for _, v := range ybCommunityQuestionLikeTeaseList {
+		ybCommunityQuestionLikeTeaseMap[v.CommunityQuestionID] = v
+	}
+
+	// 获取点赞和吐槽汇总数
+	likeMap := make(map[uint32]int)
+	teaseMap := make(map[uint32]int)
+
+	likeList, err := yb_community_question_like_tease.GetLikeNumCommentByCommunityQuestionIds(idArr)
+	if err != nil {
+		return
+	}
+	for _, v := range likeList {
+		likeMap[v.CommunityQuestionID] = v.Total
+	}
+
+	teaseList, err := yb_community_question_like_tease.GetTeaseNumCommentByCommunityQuestionIds(idArr)
+	if err != nil {
+		return
+	}
+	for _, v := range teaseList {
+		teaseMap[v.CommunityQuestionID] = v.Total
+	}
+
+	for _, v := range questionList {
+		if tmpTotal, ok := likeMap[uint32(v.CommunityQuestionID)]; ok {
+			v.LikeTotal = tmpTotal
+		}
+		if tmpTotal, ok := teaseMap[uint32(v.CommunityQuestionID)]; ok {
+			v.TeaseTotal = tmpTotal
+		}
+
+		if ybCommunityQuestionLikeTease, ok := ybCommunityQuestionLikeTeaseMap[uint32(v.CommunityQuestionID)]; ok {
+			//类型. 1-点赞 2-吐槽
+			v.OpType = ybCommunityQuestionLikeTease.OpType
+		}
+	}
+	return
+}

+ 9 - 9
models/request/comment/comment.go

@@ -1,15 +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" `
+	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"`
-}
+	CommentId uint64 `description:"留言ID" json:"comment_id"`
+}

+ 21 - 0
models/request/community.go

@@ -54,3 +54,24 @@ type VideoPlayLogReq struct {
 	VideoId     int `json:"video_id" description:"视频ID"`
 	SourceAgent int `json:"source_agent" description:"来源:1-小程序 2-小程序PC 3-公众号 4-Web官网"`
 }
+
+// ReqCommunityQuestionLikeTease 问答点赞/吐槽请求
+type ReqCommunityQuestionLikeTease struct {
+	CommunityQuestionId uint32 `description:"问答id" json:"community_question_id" `
+	OpType              int8   `description:"类型. 1-点赞 2-吐槽" json:"op_type"`
+	Enable              int8   `description:"状态. 0-无效数据(已取消点赞/吐槽) 1-有效数据(点赞/吐槽)" json:"enable"`
+	SourceAgent         int8   `description:"点赞入口来源,1:小程序,2:小程序pc" json:"source_agent"`
+}
+
+// ReqComment 问答新增评论请求
+type ReqComment struct {
+	CommunityQuestionID uint32 `description:"问答id" json:"community_question_id" `
+	Content             string `description:"留言内容" json:"content"`
+	IsShowName          int8   `description:"是否匿名 0-匿名,1-不匿名" json:"is_show_name"`
+	SourceAgent         int8   `description:"留言入口来源,1:小程序,2:pc" json:"source_agent"`
+}
+
+// ReqDel 删除评论
+type ReqDel struct {
+	CommunityQuestionCommentID uint64 `description:"留言ID" json:"community_question_comment_id"`
+}

+ 14 - 14
models/response/comment.go

@@ -3,19 +3,19 @@ package response
 import "time"
 
 type RespCommentList struct {
-	List       []*RespCommentItem   `json:"list"`
-	Paging     *PagingItem  		`json:"paging"`
+	List   []*RespCommentItem `json:"list"`
+	Paging *PagingItem        `json:"paging"`
 }
 type RespMyCommentList struct {
-	List       []*RespCommentItem   `json:"list"`
-	IsShowName int8 `description:"是否匿名 0-匿名,1-不匿名" json:"is_show_name"`
+	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""`
+	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"`
@@ -25,15 +25,15 @@ type RespCommentItem struct {
 }
 
 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"`
+	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"`
+	CommentId uint64 `description:"留言ID" json:"comment_id"`
 }

+ 45 - 1
models/response/community.go

@@ -1,5 +1,7 @@
 package response
 
+import "time"
+
 type CommunityQuestionItem struct {
 	CommunityQuestionID     int    `json:"community_question_id"`
 	UserId                  int    `json:"user_id"`
@@ -20,7 +22,13 @@ type CommunityQuestionItem struct {
 	ReplyStatus             int    `json:"reply_status" description:"回复状态 1-待分配 2-待回答 3-已回答"`
 	//AuthOk                  bool                          `json:"auth_ok" description:"是否有权限"`
 	//PermissionInfo          PermissionCheckInfo           `json:"permission_info"`
-	AudioList []*CommunityQuestionAudioItem `json:"audio_list"`
+	AudioList       []*CommunityQuestionAudioItem `json:"audio_list"`
+	OpType          int8                          `description:"类型. 1-点赞 2-吐槽" json:"op_type"`
+	LikeTotal       int                           `json:"like_total" description:"点赞数"`
+	TeaseTotal      int                           `json:"tease_total" description:"吐槽数"`
+	CommentTotal    int                           `json:"comment_total" description:"总共评论数"`
+	Comment         string                        `json:"comment" description:"评论"`
+	CommentUserName string                        `json:"comment_user_name" description:"评论人"`
 }
 
 type CommunityQuestionAudioItem struct {
@@ -77,3 +85,39 @@ type CommunityVideoItem struct {
 	ModifyTime          string `json:"modify_time"`
 	ChartPermissionName string `json:"chart_permission_name"`
 }
+
+// RespCommunityQuestionLikeTease
+type RespCommunityQuestionLikeTease struct {
+	LikeTotal  int64 `description:"点赞总数" json:"like_total"`
+	TeaseTotal int64 `description:"吐槽总数" json:"tease_total"`
+	OpType     int8  `description:"类型. 1-点赞 2-吐槽" json:"op_type"`
+	Enabled    int8  `description:"本次点赞/吐槽结果: 0-已取消赞 1-有效赞" json:"enabled"`
+}
+
+// RespCommunityQuestionCommentAdd 新增问答留言返回
+type RespCommunityQuestionCommentAdd struct {
+	CommunityQuestionCommentID uint64 `description:"留言ID" json:"community_question_comment_id"`
+}
+
+// RespCommunityQuestionCommentItem 问答留言列表的数据返回
+type RespCommunityQuestionCommentItem struct {
+	CommunityQuestionCommentID uint64    `description:"留言ID" json:"community_question_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
+}
+
+// RespCommunityQuestionCommentList 问答留言列表接口返回
+type RespCommunityQuestionCommentList struct {
+	List     []*RespCommunityQuestionCommentItem `json:"list"`
+	Paging   *PagingItem                         `json:"paging"`
+	HotTotal int64                               `json:"hot_total"`
+	MyTotal  int64                               `json:"my_total"`
+}

+ 6 - 1
models/tables/admin/query.go

@@ -20,4 +20,9 @@ func GetAdminByMobile(mobile string) (item *Admin, err error) {
 func GetAdminByEmail(mobile string) (item *Admin, err error) {
 	err = global.DEFAULT_MYSQL.Model(Admin{}).Where("email = ? AND enabled = 1", mobile).First(&item).Error
 	return
-}
+}
+
+// GetVWangInfo 获取沛总的账户信息
+func GetVWangInfo() (item *Admin, err error) {
+	return GetByAdminId(66)
+}

+ 67 - 0
models/tables/company_approval_message/company_approval_message.go

@@ -0,0 +1,67 @@
+package company_approval_message
+
+import (
+	"time"
+)
+
+// CompanyApprovalMessage [...]
+type CompanyApprovalMessage struct {
+	ID                int       `gorm:"primaryKey;column:id;type:int(11);not null" json:"-"`
+	CreateUserID      int       `gorm:"column:create_user_id;type:int(11);default:0" json:"createUserId"`                             // 消息创建者id
+	ReceiveUserID     int       `gorm:"index:idx_receive_user_id;column:receive_user_id;type:int(11);default:0" json:"receiveUserId"` // 消息接收者id
+	MessageStatus     int       `gorm:"column:message_status;type:int(11);default:0" json:"messageStatus"`                            // 消息状态:0未读,1:已读,2:作废
+	Remark            string    `gorm:"column:remark;type:varchar(500);default:''" json:"remark"`                                     // 备注信息
+	Content           string    `gorm:"column:content;type:varchar(500);default:''" json:"content"`                                   // 消息内容
+	CompanyID         int       `gorm:"column:company_id;type:int(11)" json:"companyId"`                                              // 客户id
+	CompanyName       string    `gorm:"column:company_name;type:varchar(500)" json:"companyName"`                                     // 客户名称
+	CreateTime        time.Time `gorm:"column:create_time;type:datetime" json:"createTime"`                                           // 创建时间
+	ModifyTime        time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                           // 修改时间
+	CompanyApprovalID int       `gorm:"column:company_approval_id;type:int(11);default:0" json:"companyApprovalId"`                   // 审批单id
+	ApprovalStatus    int8      `gorm:"column:approval_status;type:tinyint(4);default:0" json:"approvalStatus"`                       // 审批状态:1:待审批,2:已审批,3:已驳回
+	OperationStatus   int8      `gorm:"column:operation_status;type:tinyint(4);default:0" json:"operationStatus"`                     // 1:待审批,2:已审批
+	MessageType       int8      `gorm:"column:message_type;type:tinyint(4);default:0" json:"messageType"`                             // 1:申请消息,2:审批结果,3:文字消息
+	SourceType        int8      `gorm:"index:idx_source_typ;column:source_type;type:tinyint(4);default:1" json:"sourceType"`          // 消息来源类型,1:客户,2:合同,3:用印,4:指标替换,5:问答社区,6:问答评论
+	MessageInfo       string    `gorm:"column:message_info;type:text" json:"messageInfo"`                                             // 消息主要内容,json数据
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *CompanyApprovalMessage) TableName() string {
+	return "company_approval_message"
+}
+
+// CompanyApprovalMessageColumns get sql column name.获取数据库列名
+var CompanyApprovalMessageColumns = struct {
+	ID                string
+	CreateUserID      string
+	ReceiveUserID     string
+	MessageStatus     string
+	Remark            string
+	Content           string
+	CompanyID         string
+	CompanyName       string
+	CreateTime        string
+	ModifyTime        string
+	CompanyApprovalID string
+	ApprovalStatus    string
+	OperationStatus   string
+	MessageType       string
+	SourceType        string
+	MessageInfo       string
+}{
+	ID:                "id",
+	CreateUserID:      "create_user_id",
+	ReceiveUserID:     "receive_user_id",
+	MessageStatus:     "message_status",
+	Remark:            "remark",
+	Content:           "content",
+	CompanyID:         "company_id",
+	CompanyName:       "company_name",
+	CreateTime:        "create_time",
+	ModifyTime:        "modify_time",
+	CompanyApprovalID: "company_approval_id",
+	ApprovalStatus:    "approval_status",
+	OperationStatus:   "operation_status",
+	MessageType:       "message_type",
+	SourceType:        "source_type",
+	MessageInfo:       "message_info",
+}

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

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

+ 1 - 0
models/tables/company_approval_message/query.go

@@ -0,0 +1 @@
+package company_approval_message

+ 17 - 0
models/tables/company_approval_message/update.go

@@ -0,0 +1,17 @@
+package company_approval_message
+
+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
+}*/
+
+// Cancel 消息作废
+func Cancel(companyApprovalId int, sourceType int8) (err error) {
+	sql1 := ` UPDATE company_approval_message SET message_status=2,modify_time=NOW() 
+WHERE company_approval_id=? AND source_type=?  AND message_type=1 AND operation_status=1`
+	err = global.DEFAULT_MYSQL.Exec(sql1, companyApprovalId, sourceType).Error
+	return
+}

+ 18 - 0
models/tables/yb_comment_anonymous_user/create.go

@@ -0,0 +1,18 @@
+package yb_comment_anonymous_user
+
+import (
+	"hongze/hongze_yb/global"
+	"time"
+)
+
+func (item *YbCommentAnonymousUser) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommentAnonymousUser{}).Create(item).Error
+	return
+}
+
+// CreateBySql 通过sql创建记录
+func CreateBySql(userId uint64, createTime time.Time) (err error) {
+	sql := "INSERT INTO `yb_comment_anonymous_user` (`user_id`,`create_time`) VALUES (?,?)"
+	err = global.DEFAULT_MYSQL.Exec(sql, userId, createTime).Error
+	return
+}

+ 15 - 0
models/tables/yb_comment_anonymous_user/query.go

@@ -0,0 +1,15 @@
+package yb_comment_anonymous_user
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+// GetByUserId 根据用户ID,查询记录
+func GetByUserId(userId uint64) (item *YbCommentAnonymousUser, err error) {
+	err = global.DEFAULT_MYSQL.Where("user_id =  ? ", userId).First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}

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

@@ -0,0 +1,25 @@
+package yb_comment_anonymous_user
+
+import (
+	"time"
+)
+
+// YbCommentAnonymousUser 问答社区评论匿名表
+type YbCommentAnonymousUser struct {
+	UserID     uint64    `gorm:"primaryKey;column:user_id;type:bigint(9) unsigned;not null;default:0" json:"-"` // 用户id
+	CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP" json:"createTime"` // 添加时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbCommentAnonymousUser) TableName() string {
+	return "yb_comment_anonymous_user"
+}
+
+// YbCommentAnonymousUserColumns get sql column name.获取数据库列名
+var YbCommentAnonymousUserColumns = struct {
+	UserID     string
+	CreateTime string
+}{
+	UserID:     "user_id",
+	CreateTime: "create_time",
+}

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

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

+ 119 - 0
models/tables/yb_community_question_comment/query.go

@@ -0,0 +1,119 @@
+package yb_community_question_comment
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+// GetByCommunityQuestionCommentId 根据留言ID,查询留言
+func GetByCommunityQuestionCommentId(communityQuestionCommentId uint64) (item *YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Where("community_question_comment_id =  ? ", communityQuestionCommentId).First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetListByUserIdCommunityQuestionID 获取用户的留言列表
+func GetListByUserIdCommunityQuestionID(userId uint64, communityQuestionID int) (list []*YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("user_id = ? AND community_question_id = ? AND enabled = 1 ", userId, communityQuestionID).
+		Order("create_time desc, community_question_comment_id desc").
+		Scan(&list).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetListTotalByUserIdCommunityQuestionID 获取用户的留言总条数
+func GetListTotalByUserIdCommunityQuestionID(userId uint64, communityQuestionID int) (total int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("user_id = ? AND community_question_id = ? AND enabled = 1 ", userId, communityQuestionID).
+		Count(&total).Error
+	return
+}
+
+// GetHotListByCommunityQuestionID 获取报告的精选留言列表
+func GetHotListByCommunityQuestionID(communityQuestionID int, offset, limit int) (list []*YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("community_question_id = ? AND enabled = 1 AND is_hot = 1 AND type = 1", communityQuestionID).
+		Order("is_top desc, hot_top_time desc, community_question_comment_id desc").
+		Offset(offset).
+		Limit(limit).
+		Scan(&list).Error
+	return
+}
+
+// GetHotListTotalByCommunityQuestionID 获取精选留言总条数
+func GetHotListTotalByCommunityQuestionID(communityQuestionID int) (total int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("community_question_id = ? AND enabled = 1 AND is_hot = 1 AND type = 1", communityQuestionID).
+		Count(&total).Error
+	return
+}
+
+// GetReplyListByReplyCommentId 获取报告的精选留言的回复列表
+func GetReplyListByReplyCommentId(replyCommentIds []uint64) (list []*YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("enabled = 1 and type = 2 and reply_comment_id in ?", replyCommentIds).
+		Order("community_question_comment_id asc").
+		Scan(&list).Error
+	return
+}
+
+type SimpleYbCommunityQuestionComment struct {
+	CommunityQuestionCommentID uint64 `gorm:"primaryKey;column:community_question_comment_id;type:bigint(20) unsigned;not null" json:"-"`
+	UserID                     uint64 `gorm:"column:user_id;type:bigint(20) unsigned;not null;default:0" json:"userId"` // 用户id
+	Type                       int8   `gorm:"column:type;type:tinyint(1);not null;default:1" json:"type"`               // 留言类型 1-评论 2-回复
+	Enabled                    int8   `gorm:"column:enabled;type:tinyint(1);not null;default:1" json:"enabled"`         // 是否有效, 0-无效留言 1-有效留言
+}
+
+// GetSimpleByCommentId 根据留言ID,查询留言
+func GetSimpleByCommentId(commentId uint64) (item *SimpleYbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Select("community_question_comment_id, user_id, type, enabled").
+		Where("community_question_comment_id = ?", commentId).First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetMyLatestComment 获取用户最新的留言
+func GetMyLatestComment(userId uint64) (item *YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Select("comment_id, user_id, type, enabled, is_show_name").
+		Where("user_id = ? and type=1", userId).Order("community_question_comment_id desc").First(&item).Error
+	return
+}
+
+// NumCommentByCommunityQuestion 评论统计结构体
+type NumCommentByCommunityQuestion struct {
+	CommunityQuestionID uint32 `json:"community_question_id"`
+	Total               int    `json:"total"`
+}
+
+// GetNumCommentByCommunityQuestionIds 获取用户留言的汇总数
+func GetNumCommentByCommunityQuestionIds(communityQuestionIds []uint32, userId uint64) (item []*NumCommentByCommunityQuestion, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Select("community_question_id, count(1) total").
+		Where("community_question_id in (?) and type=1 and enabled = 1 and (is_hot = 1 or user_id=?) ", communityQuestionIds, userId).Group("community_question_id").Scan(&item).Error
+	return
+}
+
+// GetLastHotListByCommunityQuestionIds 根据问答id列表获取最近精选的留言
+func GetLastHotListByCommunityQuestionIds(communityQuestionIds []uint32) (items []*YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("community_question_comment_id in (SELECT MAX(community_question_comment_id) AS community_question_comment_id FROM yb_community_question_comment WHERE community_question_id IN (?) AND enabled = 1 AND is_hot = 1 AND type = 1 GROUP BY community_question_id)", communityQuestionIds).
+		Find(&items).Error
+	return
+}
+
+// GetLastMyListByCommunityQuestionIds 根据问答id列表获取我最近的留言
+func GetLastMyListByCommunityQuestionIds(userId uint64, communityQuestionIds []uint32) (items []*YbCommunityQuestionComment, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionComment{}).
+		Where("community_question_comment_id in (SELECT MAX(community_question_comment_id) AS community_question_comment_id FROM yb_community_question_comment WHERE user_id=? AND community_question_id IN (?) AND enabled = 1 AND type = 1 GROUP BY community_question_id)", userId, communityQuestionIds).
+		Find(&items).Error
+	return
+}

+ 40 - 0
models/tables/yb_community_question_comment/update.go

@@ -0,0 +1,40 @@
+package yb_community_question_comment
+
+import "hongze/hongze_yb/global"
+
+// Update 更新对应字段数据
+func (item *YbCommunityQuestionComment) Update(updateCols []string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(item).Select(updateCols).Updates(*item).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_community_question_comment
+			SET
+            	enabled = 0,
+				modify_time = NOW(),
+				is_hot = 0,
+				is_top = 0
+			WHERE type = 1 and user_id = ? and community_question_comment_id = ?`
+	err = tx.Exec(sql1, userId, commentId).Error
+	if err != nil {
+		return
+	}
+	// 删除相关联的回复
+	sql2 := ` UPDATE yb_community_question_comment
+			SET
+            	enabled = 0,
+				modify_time = NOW()
+			WHERE reply_comment_id = ? and type = 2`
+	err = tx.Exec(sql2, commentId).Error
+	return
+}

+ 70 - 0
models/tables/yb_community_question_comment/yb_community_question_comment.go

@@ -0,0 +1,70 @@
+package yb_community_question_comment
+
+import (
+	"time"
+)
+
+// YbCommunityQuestionComment 研报问答社区 用户留言表
+type YbCommunityQuestionComment struct {
+	CommunityQuestionCommentID uint64    `gorm:"primaryKey;column:community_question_comment_id;type:bigint(20) unsigned;not null" json:"-"`
+	CommunityQuestionID        uint32    `gorm:"column:community_question_id;type:int(10) unsigned;not null;default:0" json:"communityQuestionId"` // 问答ID
+	UserID                     uint64    `gorm:"column:user_id;type:bigint(20) unsigned;not null;default:0" json:"userId"`                         // 用户id
+	RealName                   string    `gorm:"column:real_name;type:varchar(255);not null;default:''" json:"realName"`                           // 用户当时昵称
+	Content                    string    `gorm:"column:content;type:text" json:"content"`                                                          // 留言内容
+	ReplyCommentID             uint64    `gorm:"column:reply_comment_id;type:bigint(20) unsigned;not null;default:0" json:"replyCommentId"`        // 回复的留言ID
+	IsTop                      int8      `gorm:"column:is_top;type:tinyint(2);not null;default:0" json:"isTop"`                                    // 是否置顶(0-未置顶,1-置顶)
+	IsHot                      int8      `gorm:"column:is_hot;type:tinyint(2);not null;default:0" json:"isHot"`                                    // 是否设置精选(0-未设置,1-已设置)
+	HotTopTime                 time.Time `gorm:"column:hot_top_time;type:datetime" json:"hotTopTime"`                                              // 设置精选或者设置置顶的时间
+	Type                       int8      `gorm:"column:type;type:tinyint(1);not null;default:1" json:"type"`                                       // 留言类型 1-评论 2-回复
+	Enabled                    int8      `gorm:"column:enabled;type:tinyint(1);not null;default:1" json:"enabled"`                                 // 是否有效, 0-无效留言 1-有效留言
+	IsShowName                 int8      `gorm:"column:is_show_name;type:tinyint(1);not null;default:0" json:"isShowName"`                         // 是否匿名 0-匿名,1-不匿名
+	SourceAgent                int8      `gorm:"column:source_agent;type:tinyint(1);not null;default:1" json:"sourceAgent"`                        // 留言入口来源,1:小程序,2:小程序pc, 4:web pc
+	TopTime                    time.Time `gorm:"column:top_time;type:datetime" json:"topTime"`                                                     // 设置置顶的时间
+	HotTime                    time.Time `gorm:"column:hot_time;type:datetime" json:"hotTime"`                                                     // 设置精选的时间
+	ModifyTime                 time.Time `gorm:"column:modify_time;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"modifyTime"`            // 修改时间
+	CreateTime                 time.Time `gorm:"column:create_time;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"createTime"`            // 创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbCommunityQuestionComment) TableName() string {
+	return "yb_community_question_comment"
+}
+
+// YbCommunityQuestionCommentColumns get sql column name.获取数据库列名
+var YbCommunityQuestionCommentColumns = struct {
+	CommunityQuestionCommentID string
+	CommunityQuestionID        string
+	UserID                     string
+	RealName                   string
+	Content                    string
+	ReplyCommentID             string
+	IsTop                      string
+	IsHot                      string
+	HotTopTime                 string
+	Type                       string
+	Enabled                    string
+	IsShowName                 string
+	SourceAgent                string
+	TopTime                    string
+	HotTime                    string
+	ModifyTime                 string
+	CreateTime                 string
+}{
+	CommunityQuestionCommentID: "community_question_comment_id",
+	CommunityQuestionID:        "community_question_id",
+	UserID:                     "user_id",
+	RealName:                   "real_name",
+	Content:                    "content",
+	ReplyCommentID:             "reply_comment_id",
+	IsTop:                      "is_top",
+	IsHot:                      "is_hot",
+	HotTopTime:                 "hot_top_time",
+	Type:                       "type",
+	Enabled:                    "enabled",
+	IsShowName:                 "is_show_name",
+	SourceAgent:                "source_agent",
+	TopTime:                    "top_time",
+	HotTime:                    "hot_time",
+	ModifyTime:                 "modify_time",
+	CreateTime:                 "create_time",
+}

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

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

+ 72 - 0
models/tables/yb_community_question_like_tease/query.go

@@ -0,0 +1,72 @@
+package yb_community_question_like_tease
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+// GetByUserIdAndCommunityQuestionId 根据用户和问答id获取点赞/吐槽记录
+func GetByUserIdAndCommunityQuestionId(userId uint64, communityQuestionId uint32) (item *YbCommunityQuestionLikeTease, err error) {
+	err = global.DEFAULT_MYSQL.
+		Where("user_id = ? AND community_question_id = ?", userId, communityQuestionId).
+		First(&item).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	return
+}
+
+// GetLikeNumByCommunityQuestionId 获取某个问答的点赞数
+func GetLikeNumByCommunityQuestionId(communityQuestionId uint32) (num int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionLikeTease{}).
+		Where(" community_question_id = ? AND enabled=1 AND op_type = 1 ", communityQuestionId).
+		Count(&num).Error
+	return
+}
+
+// GetTeaseNumByCommunityQuestionId 获取某个问答的吐槽数
+func GetTeaseNumByCommunityQuestionId(communityQuestionId uint32) (num int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionLikeTease{}).
+		Where(" community_question_id = ? AND enabled=1 AND op_type = 2 ", communityQuestionId).
+		Count(&num).Error
+	return
+}
+
+// NumCommentByCommunityQuestionIds 评论统计结构体
+type NumCommentByCommunityQuestionIds struct {
+	CommunityQuestionID uint32 `json:"community_question_id"`
+	Total               int    `json:"total"`
+}
+
+// GetLikeNumCommentByCommunityQuestionIds 根据问答id列表获取所有问答的点赞数
+func GetLikeNumCommentByCommunityQuestionIds(communityQuestionIds []uint32) (items []*NumCommentByCommunityQuestionIds, err error) {
+	if len(communityQuestionIds) <= 0 {
+		return
+	}
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionLikeTease{}).
+		Select("community_question_id, count(1) total").
+		Where("community_question_id in (?) AND enabled=1  AND op_type=1", communityQuestionIds).Group("community_question_id").Scan(&items).Error
+	return
+}
+
+// GetTeaseNumCommentByCommunityQuestionIds 根据问答id列表获取所有问答的吐槽数
+func GetTeaseNumCommentByCommunityQuestionIds(communityQuestionIds []uint32) (items []*NumCommentByCommunityQuestionIds, err error) {
+	if len(communityQuestionIds) <= 0 {
+		return
+	}
+	err = global.DEFAULT_MYSQL.Model(YbCommunityQuestionLikeTease{}).
+		Select("community_question_id, count(1) total").
+		Where("community_question_id in (?) AND enabled=1  AND op_type=2", communityQuestionIds).Group("community_question_id").Scan(&items).Error
+	return
+}
+
+// GetByUserIdAndCommunityQuestionIds 根据用户id和问答id列表获取成功点赞/吐槽记录
+func GetByUserIdAndCommunityQuestionIds(userId uint64, communityQuestionIds []uint32) (items []*YbCommunityQuestionLikeTease, err error) {
+	if len(communityQuestionIds) <= 0 {
+		return
+	}
+	err = global.DEFAULT_MYSQL.
+		Where("user_id = ? AND enabled=1  AND community_question_id in (?)", userId, communityQuestionIds).Group("community_question_id").
+		Find(&items).Error
+	return
+}

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

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

+ 43 - 0
models/tables/yb_community_question_like_tease/yb_community_question_like_tease.go

@@ -0,0 +1,43 @@
+package yb_community_question_like_tease
+
+import (
+	"time"
+)
+
+// YbCommunityQuestionLikeTease 问答点赞/吐槽表
+type YbCommunityQuestionLikeTease struct {
+	CommunityQuestionLikeTeaseID uint64    `gorm:"primaryKey;column:community_question_like_tease_id;type:bigint(20) unsigned;not null" json:"-"`    // 点赞/吐槽自增id
+	UserID                       uint64    `gorm:"column:user_id;type:bigint(20) unsigned;not null;default:0" json:"userId"`                         // 用户id
+	OpType                       int8      `gorm:"column:op_type;type:tinyint(1);not null;default:1" json:"opType"`                                  // 类型. 1-点赞 2-吐槽
+	Enabled                      int8      `gorm:"column:enabled;type:tinyint(1);not null;default:1" json:"enabled"`                                 // 状态. 0-无效数据(已取消点赞/吐槽) 1-有效数据(点赞/吐槽)
+	CreateTime                   time.Time `gorm:"column:create_time;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"createTime"`            // 创建时间
+	ModifyTime                   time.Time `gorm:"column:modify_time;type:datetime;not null;default:CURRENT_TIMESTAMP" json:"modifyTime"`            // 修改时间
+	CommunityQuestionID          uint32    `gorm:"column:community_question_id;type:int(10) unsigned;not null;default:0" json:"communityQuestionId"` // 问答ID
+	SourceAgent                  int8      `gorm:"column:source_agent;type:tinyint(1);not null;default:0" json:"sourceAgent"`                        // 点赞/吐槽入口来源,1:小程序,2:小程序pc, 4:web pc
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbCommunityQuestionLikeTease) TableName() string {
+	return "yb_community_question_like_tease"
+}
+
+// YbCommunityQuestionLikeTeaseColumns get sql column name.获取数据库列名
+var YbCommunityQuestionLikeTeaseColumns = struct {
+	CommunityQuestionLikeTeaseID string
+	UserID                       string
+	OpType                       string
+	Enabled                      string
+	CreateTime                   string
+	ModifyTime                   string
+	CommunityQuestionID          string
+	SourceAgent                  string
+}{
+	CommunityQuestionLikeTeaseID: "community_question_like_tease_id",
+	UserID:                       "user_id",
+	OpType:                       "op_type",
+	Enabled:                      "enabled",
+	CreateTime:                   "create_time",
+	ModifyTime:                   "modify_time",
+	CommunityQuestionID:          "community_question_id",
+	SourceAgent:                  "source_agent",
+}

+ 13 - 2
routers/community.go

@@ -6,8 +6,9 @@ import (
 	"hongze/hongze_yb/middleware"
 )
 
-func InitCommunity(r *gin.Engine)  {
+func InitCommunity(r *gin.Engine) {
 	rGroup := r.Group("api/community").Use(middleware.Token(), middleware.CheckBaseAuth())
+
 	// 问答社区
 	rGroup.GET("/question/list", community.QuestionList)
 	rGroup.GET("/question/detail", community.QuestionDetail)
@@ -23,4 +24,14 @@ func InitCommunity(r *gin.Engine)  {
 	noAuthGroup := r.Group("api/community").Use(middleware.Token())
 	noAuthGroup.GET("/video/list", community.VideoList)
 	noAuthGroup.POST("/video/play_log", community.VideoPlayLog)
-}
+
+	//点赞、吐槽、评论
+	rGroup.POST("/set_like_or_tease", community.SetLikeOrTease)
+	rGroup.POST("/comment", community.Comment)
+	rGroup.POST("/comment/delete", community.DeleteComment)
+	rGroup.GET("/need_anonymous_user_tips", community.GetNeedCommentAnonymousUserTips)
+	rGroup.POST("/set_anonymous_user_tips", community.SetCommentAnonymousUserTips)
+	rGroup.GET("/comment/hot", community.HotList)
+	rGroup.GET("/comment/my", community.MyList)
+
+}

+ 121 - 17
services/community/question.go

@@ -3,13 +3,20 @@ package community
 import (
 	"errors"
 	"fmt"
+	"hongze/hongze_yb/global"
 	"hongze/hongze_yb/models/request"
 	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/admin"
+	"hongze/hongze_yb/models/tables/company"
+	"hongze/hongze_yb/models/tables/company_product"
 	"hongze/hongze_yb/models/tables/research_group"
 	"hongze/hongze_yb/models/tables/user_record"
+	"hongze/hongze_yb/models/tables/wx_user"
 	"hongze/hongze_yb/models/tables/yb_community_audio_listen_log"
 	"hongze/hongze_yb/models/tables/yb_community_question"
 	"hongze/hongze_yb/models/tables/yb_community_question_audio"
+	"hongze/hongze_yb/services/alarm_msg"
+	"hongze/hongze_yb/services/company_approval_message"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/services/wechat"
 	"hongze/hongze_yb/utils"
@@ -29,8 +36,8 @@ func GetQuestionList(pageIndex, pageSize, onlyMine, varietyTagId, replyStatus, g
 		return
 	}
 	if onlyMine == 1 {
-		if isResearcher {  //如果是研究员
-			if replyStatus == 4  {  //分配给研究员未回答的问题
+		if isResearcher { //如果是研究员
+			if replyStatus == 4 { //分配给研究员未回答的问题
 				condition += " and replier_user_id=? and reply_status = 2"
 				pars = append(pars, userInfo.UserID)
 			} else if replyStatus == 2 { //研究员提问的问题未分配或者未回答的问题
@@ -39,20 +46,20 @@ func GetQuestionList(pageIndex, pageSize, onlyMine, varietyTagId, replyStatus, g
 			} else if replyStatus == 3 { //分配给研究员的已回答和研究员提问的被回答的问题
 				condition += " and (replier_user_id=? or user_id=?) and reply_status =3"
 				pars = append(pars, userInfo.UserID, userInfo.UserID)
-			}else if replyStatus == 0 {  //分配给研究员或者研究员提问的所以问题
+			} else if replyStatus == 0 { //分配给研究员或者研究员提问的所以问题
 				condition += " and (replier_user_id=? or user_id=?)"
 				pars = append(pars, userInfo.UserID, userInfo.UserID)
 			}
 		} else {
 			condition += " and user_id=?"
 			pars = append(pars, userInfo.UserID)
-			if replyStatus == 2 {  // 普通用户未回答为待分配和未回答
+			if replyStatus == 2 { // 普通用户未回答为待分配和未回答
 				condition += " and reply_status >0 and reply_status <3"
-			} else if replyStatus == 3{
+			} else if replyStatus == 3 {
 				condition += " and reply_status = 3"
 			}
 		}
-	}else{
+	} else {
 		if replyStatus == 3 {
 			condition += " and reply_status = 3"
 		}
@@ -121,8 +128,8 @@ func GetQuestionList(pageIndex, pageSize, onlyMine, varietyTagId, replyStatus, g
 			ReplierRealName:         v.ReplierRealName,
 			ReplierRank:             replierRank,
 			ReplierAvatar:           avatar,
-			VarietyTagId:       v.VarietyTagID,
-			VarietyTagName:     v.VarietyTagName,
+			VarietyTagId:            v.VarietyTagID,
+			VarietyTagName:          v.VarietyTagName,
 			ResearchGroupSecondId:   v.ResearchGroupSecondID,
 			ResearchGroupSecondName: v.ResearchGroupSecondName,
 			IsRead:                  v.IsRead,
@@ -188,8 +195,8 @@ func GetQuestionDetail(questionId int, userInfo user.UserInfo) (item *response.C
 		ReplierRealName:         detail.ReplierRealName,
 		ReplierRank:             replierRank,
 		ReplierAvatar:           detail.ReplierAvatar,
-		VarietyTagId:       detail.VarietyTagID,
-		VarietyTagName:     detail.VarietyTagName,
+		VarietyTagId:            detail.VarietyTagID,
+		VarietyTagName:          detail.VarietyTagName,
 		ResearchGroupSecondId:   detail.ResearchGroupSecondID,
 		ResearchGroupSecondName: detail.ResearchGroupSecondName,
 		IsRead:                  detail.IsRead,
@@ -199,7 +206,7 @@ func GetQuestionDetail(questionId int, userInfo user.UserInfo) (item *response.C
 		ReplyTime:               detail.ReplyTime.Format(utils.FormatDateTime),
 		//AuthOk:                  authOk,
 		//PermissionInfo:          permissionInfo,
-		AudioList:               audios,
+		AudioList: audios,
 	}
 	errMsg = "获取成功"
 	return
@@ -230,6 +237,9 @@ func CreateQuestion(userId int, mobile, realName, content string) (err error) {
 	if e := item.Create(); e != nil {
 		err = errors.New("新增问题失败 Err:" + e.Error())
 	}
+
+	// 新增问答后,消息通知管理员
+	go messageToAdmin(userId, item)
 	return
 }
 
@@ -351,20 +361,20 @@ func GetQuestionListTotal(userInfo user.UserInfo) (resp *response.CommunityQuest
 		total += v.Total
 		if isResearcher {
 			if v.UserId == userInfo.UserID {
-				if v.ReplyStatus == 1 || v.ReplyStatus == 2 {  //研究员提问的待分配的问题
+				if v.ReplyStatus == 1 || v.ReplyStatus == 2 { //研究员提问的待分配的问题
 					wait += v.Total
 				}
 			}
-			if v.ReplierUserId == userInfo.UserID  && v.ReplyStatus == 2{ //分配给研究员的未回答的问题
+			if v.ReplierUserId == userInfo.UserID && v.ReplyStatus == 2 { //分配给研究员的未回答的问题
 				distribute += v.Total
 			}
 			if v.ReplyStatus == 3 {
 				replied += v.Total
 			}
-		}else{
-			if v.ReplyStatus == 1 || v.ReplyStatus == 2 {  //未分配和未回答的数量
+		} else {
+			if v.ReplyStatus == 1 || v.ReplyStatus == 2 { //未分配和未回答的数量
 				wait += v.Total
-			}else if v.ReplyStatus == 3 {  //已回答的数量
+			} else if v.ReplyStatus == 3 { //已回答的数量
 				replied += v.Total
 			}
 		}
@@ -451,7 +461,7 @@ func GetResearchGroupTree() (respList []*response.ResearchGroupItem, err error)
 }
 
 // AddAudioListenLog 添加用户点击音频日志
-func AddAudioListenLog(userInfo user.UserInfo, audioId int, sourceAgent int) (err error)  {
+func AddAudioListenLog(userInfo user.UserInfo, audioId int, sourceAgent int) (err error) {
 	//1. 查询音频是否存在
 	audio, err := yb_community_question_audio.GetByAudioId(audioId)
 	if err != nil && err != utils.ErrNoRow {
@@ -479,3 +489,97 @@ func AddAudioListenLog(userInfo user.UserInfo, audioId int, sourceAgent int) (er
 	}
 	return
 }
+
+// messageToAdmin 添加站内消息
+func messageToAdmin(userId int, ybCommunityQuestion *yb_community_question.YbCommunityQuestion) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增社区问答完成后,发送消息给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+
+	//因为产品说只要给沛总发送信息,那么没办法咯,只去获取沛总的信息 2022-07-19 11:29:16
+	vWangInfo, err := admin.GetVWangInfo()
+	if err != nil {
+		return
+	}
+	//站内消息
+	go systemMessageToAdmin(*vWangInfo, userId, ybCommunityQuestion)
+	//微信模板消息
+	go wxMessageToAdmin(*vWangInfo, ybCommunityQuestion)
+
+	return
+}
+
+// systemMessageToAdmin 系统消息消息通知管理员
+func systemMessageToAdmin(adminInfo admin.Admin, userId int, ybCommunityQuestion *yb_community_question.YbCommunityQuestion) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增社区问答完成后,站内评论信息发送给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+	// 接收人的admin_id
+	receiveUserId := int(adminInfo.AdminID)
+
+	//获取评论人信息
+	wxUser, err := wx_user.GetByUserId(userId)
+	if err != nil {
+		return
+	}
+	var msgType, sourceType, approvalStatus int8
+	msgType = company_approval_message.CompanyApprovalMessageMessageTypeByApply
+	sourceType = company_approval_message.CompanyApprovalMessageSourceTypeByQuestion
+	approvalStatus = company_approval_message.CompanyApprovalMessageApprovalStatusByPending
+
+	companyInfo, err := company.GetByCompanyId(wxUser.CompanyID)
+	if err != nil {
+		return
+	}
+
+	productId := 1
+	companyProductInfo, err := company_product.GetByCompany2ProductId(wxUser.CompanyID, int64(productId))
+	if err != nil {
+		return
+	}
+
+	companyName := companyInfo.CompanyName
+	remark := `您有新的问答待分配`
+	content := `您有新的问答待分配`
+
+	messageInfo := company_approval_message.MessageInfo{
+		CompanyName:          companyInfo.CompanyName,
+		ProductId:            productId,
+		CompanyProductStatus: companyProductInfo.Status,
+		Title:                ybCommunityQuestion.QuestionContent,
+		Content:              ybCommunityQuestion.QuestionContent,
+		UserId:               wxUser.UserID,
+		UserName:             ybCommunityQuestion.RealName,
+		CreateTime:           ybCommunityQuestion.CreateTime,
+	}
+	//客户添加消息
+	err = company_approval_message.AddCompanyApprovalMessage(utils.AdminId, receiveUserId, int(wxUser.CompanyID), ybCommunityQuestion.CommunityQuestionID, msgType, sourceType, approvalStatus, companyName, remark, content, messageInfo)
+	return
+}
+
+// wxMessageToAdmin 微信模板消息通知管理员
+func wxMessageToAdmin(adminInfo admin.Admin, ybCommunityQuestion *yb_community_question.YbCommunityQuestion) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("新增社区问答完成后,微信模板消息发送给管理员失败"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+err.Error(), 3)
+		}
+	}()
+
+	if global.CONFIG.Serve.RunMode == "debug" {
+		adminInfo.Mobile = `18221983795`
+	}
+	wxUser, err := wx_user.GetByMobile(adminInfo.Mobile)
+	if err != nil {
+		return
+	}
+
+	err = wechat.SendQuestionToAdmin(ybCommunityQuestion.CommunityQuestionID, int(wxUser.UserID), ybCommunityQuestion.QuestionContent)
+	return
+}

+ 4 - 0
services/company/permission.go

@@ -485,6 +485,7 @@ type ChartPermissionCheckInfo struct {
 	Mobile       string       `json:"mobile" description:"手机号"`
 	Type         string       `json:"type" description:"无权限,需要前端处理的类型,枚举值:expired, apply, contact"`
 	CustomerInfo CustomerInfo `json:"customer_info" description:"客户信息"`
+	Jump         string       `json:"jump" description:"需要跳转的页面,sandbox_list"`
 }
 
 // CheckUserChartPermission 验证用户/联系人的图库权限
@@ -888,6 +889,9 @@ func CheckUserSandboxPermission(companyId int64, userId, permissionId int) (ok b
 					ok = true
 				}
 			}
+			if ok == false {
+				permissionCheckInfo.Jump = `sandbox_list` //如果是没有单个品种的权限,那么提示后并跳转到沙盘列表页吧
+			}
 		} else {
 			// 不校验品种权限的话,那么就是认为有权限的
 			if len(companyPermissionList) > 0 {

+ 80 - 0
services/company_approval_message/company_approval_message.go

@@ -0,0 +1,80 @@
+package company_approval_message
+
+import (
+	"encoding/json"
+	"hongze/hongze_yb/models/tables/company_approval_message"
+	"time"
+)
+
+//消息来源类型,1:客户,2:合同,3:用印,4:指标替换,5:问答社区,6:问答评论
+const (
+	CompanyApprovalMessageSourceTypeByCompany         = 1
+	CompanyApprovalMessageSourceTypeByContract        = 2
+	CompanyApprovalMessageSourceTypeBySeal            = 3
+	CompanyApprovalMessageSourceTypeByEdbInfo         = 4
+	CompanyApprovalMessageSourceTypeByQuestion        = 5
+	CompanyApprovalMessageSourceTypeByQuestionComment = 6
+)
+
+// 1:申请消息,2:审批结果,3:消息通知
+const (
+	CompanyApprovalMessageMessageTypeByApply          = 1
+	CompanyApprovalMessageMessageTypeByApprovalResult = 2
+	CompanyApprovalMessageMessageTypeByMessage        = 3
+)
+
+//审批状态,1:待审批,2:已审批,3:已驳回
+const (
+	CompanyApprovalMessageApprovalStatusByPending  = 1
+	CompanyApprovalMessageApprovalStatusByApproved = 2
+	CompanyApprovalMessageApprovalStatusByRejected = 3
+)
+
+// MessageInfo 消息主要内容
+type MessageInfo struct {
+	CompanyName          string    `json:"company_name"`
+	ProductId            int       `json:"product_id"`
+	CompanyProductStatus string    `json:"company_product_status"`
+	Title                string    `json:"title"`
+	Content              string    `json:"content"`
+	UserId               uint64    `json:"user_id"`
+	UserName             string    `json:"user_name"`
+	CreateTime           time.Time `json:"create_time"`
+}
+
+// AddCompanyApprovalMessage 添加系统消息
+// @params createUserId int "消息创建人id"
+// @params receiveUserId int "消息接收人id"
+// @params companyApprovalId int "消息对应的id"
+func AddCompanyApprovalMessage(createUserId, receiveUserId, companyId, companyApprovalId int, msgType, sourceType, approvalStatus int8, companyName, remark, content string, messageInfo MessageInfo) (err error) {
+	messageInfoStr, err := json.Marshal(messageInfo)
+	if err != nil {
+		return
+	}
+	msgItem := &company_approval_message.CompanyApprovalMessage{
+		//ID:                0,
+		CreateUserID:      createUserId,
+		ReceiveUserID:     receiveUserId,
+		MessageStatus:     0, //消息状态:0未读,1:已读,2:作废
+		Remark:            remark,
+		Content:           content,
+		CompanyID:         companyId,
+		CompanyName:       companyName,
+		CreateTime:        time.Now(),
+		ModifyTime:        time.Now(),
+		CompanyApprovalID: companyApprovalId,
+		ApprovalStatus:    approvalStatus,         //审批状态,1:待审批,2:已审批,3:已驳回
+		OperationStatus:   1,                      //消息状态:1:待审批,2:已审批
+		MessageType:       msgType,                //1:申请消息,2:审批结果,3:消息通知
+		SourceType:        sourceType,             //消息来源,1:客户,2:合同,3:用印
+		MessageInfo:       string(messageInfoStr), //消息主要内容,json数据
+	}
+	err = msgItem.Create()
+	return
+}
+
+// CancelCompanyApprovalMessage 消息作废
+func CancelCompanyApprovalMessage(companyApprovalId int, sourceType int8) (err error) {
+	err = company_approval_message.Cancel(companyApprovalId, sourceType)
+	return
+}

+ 123 - 1
services/wechat/template_msg.go

@@ -327,4 +327,126 @@ func SendMultiTemplateMsgNoReturn(sendMap map[string]interface{}, items []*OpenI
 		}
 	}
 	return
-}
+}
+
+// SendQuestionToAdmin 推送研报小程序模板消息-用户提问时,通知到管理员
+func SendQuestionToAdmin(questionId, userId int, questionTitle string) (err error) {
+	if userId == 0 {
+		return
+	}
+	var errMsg string
+	defer func() {
+		if err != nil {
+			alarmMsg := fmt.Sprintf("SendQuestionToAdmin-推送研报小程序模板消息-用户提问时,通知到管理员; QuestionId: %d; Err: %s; Msg: %s", questionId, err.Error(), errMsg)
+			go alarm_msg.SendAlarmMsg(alarmMsg, 3)
+		}
+	}()
+	// 校验用户是否取消关注公众号
+	userRecord, e := user_record.GetByUserId(userId, utils.USER_RECORD_PLATFORM_RDDP)
+	if e != nil {
+		// 用户无公众号信息
+		if e == utils.ErrNoRow {
+			return
+		}
+		err = errors.New("获取用户Record信息失败, Err:" + e.Error())
+		return
+	}
+	// 取消关注则不推送
+	if userRecord.Subscribe == 0 {
+		return
+	}
+
+	openIdList := make([]*OpenIdList, 0)
+	openIdList = append(openIdList, &OpenIdList{
+		OpenId: userRecord.OpenID,
+		UserId: userId,
+	})
+
+	sendMap := make(map[string]interface{})
+	sendData := make(map[string]interface{})
+
+	first := "您好,有新的提问待分配"
+	keyword1 := questionTitle
+	keyword2 := "待查看"
+	remark := "请点击详情查看回复"
+
+	sendData["first"] = map[string]interface{}{"value": first, "color": "#173177"}
+	sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": "#173177"}
+	sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": "#173177"}
+	sendData["remark"] = map[string]interface{}{"value": remark, "color": "#173177"}
+
+	sendMap["template_id"] = TemplateIdWithCommunityQuestion
+	sendMap["data"] = sendData
+
+	wxAppPath := fmt.Sprintf("/pages-question/detail/index?type=question&id=%d", questionId)
+	if global.CONFIG.Serve.RunMode == "debug" {
+		// 仅测试环境测试用
+		wxAppPath = "pages-approve/seal/list"
+	}
+	if wxAppPath != "" {
+		sendMap["miniprogram"] = map[string]interface{}{"appid": WxMobileCrmAppId, "pagepath": wxAppPath}
+	}
+	err = SendMultiTemplateMsg(sendMap, openIdList, wxAppPath, utils.TEMPLATE_MSG_YB_COMMUNITY_QUESTION)
+	return
+}
+
+// SendQuestionCommentToAdmin 推送研报小程序模板消息-用户评论问答时,通知到管理员
+func SendQuestionCommentToAdmin(commentId, userId int, commentContent string) (err error) {
+	if userId == 0 {
+		return
+	}
+	var errMsg string
+	defer func() {
+		if err != nil {
+			alarmMsg := fmt.Sprintf("SendQuestionCommentToAdmin-推送研报小程序模板消息-用户评论问答时,通知到管理员; CommentId: %d; Err: %s; Msg: %s", commentId, err.Error(), errMsg)
+			go alarm_msg.SendAlarmMsg(alarmMsg, 3)
+		}
+	}()
+	// 校验用户是否取消关注公众号
+	userRecord, e := user_record.GetByUserId(userId, utils.USER_RECORD_PLATFORM_RDDP)
+	if e != nil {
+		// 用户无公众号信息
+		if e == utils.ErrNoRow {
+			return
+		}
+		err = errors.New("获取用户Record信息失败, Err:" + e.Error())
+		return
+	}
+	// 取消关注则不推送
+	if userRecord.Subscribe == 0 {
+		return
+	}
+
+	openIdList := make([]*OpenIdList, 0)
+	openIdList = append(openIdList, &OpenIdList{
+		OpenId: userRecord.OpenID,
+		UserId: userId,
+	})
+
+	sendMap := make(map[string]interface{})
+	sendData := make(map[string]interface{})
+
+	first := "您好,有新的评论待查看"
+	keyword1 := commentContent
+	keyword2 := "待查看"
+	remark := "请点击详情查看回复"
+
+	sendData["first"] = map[string]interface{}{"value": first, "color": "#173177"}
+	sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": "#173177"}
+	sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": "#173177"}
+	sendData["remark"] = map[string]interface{}{"value": remark, "color": "#173177"}
+
+	sendMap["template_id"] = TemplateIdWithCommunityQuestion
+	sendMap["data"] = sendData
+
+	wxAppPath := fmt.Sprintf("/pages-question/detail/index?type=comment&id=%d", commentId)
+	if global.CONFIG.Serve.RunMode == "debug" {
+		// 仅测试环境测试用
+		wxAppPath = "pages-approve/seal/list"
+	}
+	if wxAppPath != "" {
+		sendMap["miniprogram"] = map[string]interface{}{"appid": WxMobileCrmAppId, "pagepath": wxAppPath}
+	}
+	err = SendMultiTemplateMsg(sendMap, openIdList, wxAppPath, utils.TEMPLATE_MSG_YB_COMMUNITY_QUESTION)
+	return
+}

+ 9 - 0
services/wechat/wechat.go

@@ -26,10 +26,19 @@ var (
 	WxYbAppId                       string // 研报小程序AppID
 	PcWxAppId                       string //pc版AppId
 	PcWxAppSecret                   string //pc版AppSecret
+
+	WxMobileCrmAppId     string //随手办公小程序appid
+	WxMobileCrmId        string //随手办公小程序id
+	WxAppMobileCrmSecret string //随手办公小程序秘钥
 )
 
 func init() {
 	WxYbAppId = "wxb059c872d79b9967"
+
+	WxMobileCrmAppId = `wx67b68e39913e511e`
+	WxMobileCrmId = `wx67b68e39913e511e`
+	WxAppMobileCrmSecret = `660b0375f701a19220bb8a662b41c77c`
+
 	if global.CONFIG.Serve.RunMode == "debug" {
 		WxAppId = "wx9b5d7291e581233a"
 		WxAppSecret = "f4d52e34021eee262dce9682b31f8861"

+ 5 - 0
utils/constants.go

@@ -153,3 +153,8 @@ 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" //弘则官方默认头像
 )
+
+const (
+	AdminId  = 11      //系统操作的用户id
+	RealName = "超级管理员" //系统操作的用户名称
+)