feat: @提及发送通知 + 通知点击定位高亮
- 新增 NotifyCommentMention 通知类型,归属 mention 分类 TAB - parseMentions 中向被@用户发送通知(排除自己和重复通知) - 消息中心 mention 通知可点击跳转至文章页面 - 通过 mention 通知进入时,来源评论置顶并持久半透明高亮 - 普通评论链接保持原有短暂高亮行为不变
This commit is contained in:
@ -11,8 +11,9 @@ const (
|
||||
NotifyLevelUp = "level_up"
|
||||
NotifyComment = "comment"
|
||||
NotifyCommentReply = "comment_reply"
|
||||
NotifyLikeAggregated = "like_aggregated" // 每日聚合点赞通知
|
||||
NotifyFollow = "follow" // 关注通知
|
||||
NotifyLikeAggregated = "like_aggregated" // 每日聚合点赞通知
|
||||
NotifyFollow = "follow" // 关注通知
|
||||
NotifyCommentMention = "comment_mention" // 评论@提及通知
|
||||
)
|
||||
|
||||
// Notification 消息/通知模型
|
||||
@ -39,6 +40,7 @@ var NotifyTypeNames = map[string]string{
|
||||
NotifyLevelUp: "等级提升",
|
||||
NotifyComment: "评论",
|
||||
NotifyCommentReply: "回复",
|
||||
NotifyCommentMention: "@ 提及",
|
||||
NotifyLikeAggregated: "点赞",
|
||||
NotifyFollow: "关注",
|
||||
}
|
||||
@ -54,6 +56,7 @@ var NotifyCategory = map[string]string{
|
||||
NotifyLevelUp: "system",
|
||||
NotifyComment: "mention",
|
||||
NotifyCommentReply: "mention",
|
||||
NotifyCommentMention: "mention",
|
||||
NotifyLikeAggregated: "like",
|
||||
NotifyFollow: "follow",
|
||||
}
|
||||
|
||||
@ -55,15 +55,15 @@ func (s *CommentService) CreateRoot(userID uint, postID uint, body string) (*mod
|
||||
// 文章评论数+1
|
||||
_ = s.repo.IncrCommentsCount(postID)
|
||||
|
||||
// 解析 @ 提及
|
||||
s.parseMentions(comment.ID, body)
|
||||
// 解析 @ 提及 + 发送通知
|
||||
commenterName, _ := s.repo.GetUsernameByID(userID)
|
||||
if commenterName == "" {
|
||||
commenterName = "用户"
|
||||
}
|
||||
s.parseMentions(comment.ID, postID, userID, commenterName, body)
|
||||
|
||||
// 通知文章作者(评论者 ≠ 作者),RelatedID 存 postID 以便消息页生成跳转链接
|
||||
if s.notifier != nil && userID != postAuthorID {
|
||||
commenterName, _ := s.repo.GetUsernameByID(userID)
|
||||
if commenterName == "" {
|
||||
commenterName = "用户"
|
||||
}
|
||||
s.notifier.Create(postAuthorID, model.NotifyComment,
|
||||
"新评论",
|
||||
fmt.Sprintf("%s 评论了你的文章", commenterName),
|
||||
@ -103,15 +103,15 @@ func (s *CommentService) CreateReply(userID uint, parentID uint, body string) (*
|
||||
// 文章评论数+1
|
||||
_ = s.repo.IncrCommentsCount(parent.PostID)
|
||||
|
||||
// 解析 @ 提及
|
||||
s.parseMentions(comment.ID, body)
|
||||
// 解析 @ 提及 + 发送通知
|
||||
commenterName, _ := s.repo.GetUsernameByID(userID)
|
||||
if commenterName == "" {
|
||||
commenterName = "用户"
|
||||
}
|
||||
s.parseMentions(comment.ID, parent.PostID, userID, commenterName, body)
|
||||
|
||||
// 通知被回复者(不自己回复自己),RelatedID 存 postID 以便消息页生成跳转链接
|
||||
if s.notifier != nil && parent.UserID != userID {
|
||||
commenterName, _ := s.repo.GetUsernameByID(userID)
|
||||
if commenterName == "" {
|
||||
commenterName = "用户"
|
||||
}
|
||||
s.notifier.Create(parent.UserID, model.NotifyCommentReply,
|
||||
"新回复",
|
||||
fmt.Sprintf("%s 回复了你的评论", commenterName),
|
||||
@ -209,10 +209,12 @@ func (s *CommentService) SearchUsers(keyword string, followerUID uint) ([]model.
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// parseMentions 解析@用户并存储到 comment_mentions 表
|
||||
func (s *CommentService) parseMentions(commentID uint, body string) {
|
||||
// parseMentions 解析@用户,存储到 comment_mentions 表,并向被@用户发送通知
|
||||
func (s *CommentService) parseMentions(commentID uint, postID uint, commenterID uint, commenterName string, body string) {
|
||||
matches := mentionPattern.FindAllStringSubmatch(body, -1)
|
||||
seen := make(map[string]bool)
|
||||
notified := make(map[uint]bool) // 防止重复通知同一用户
|
||||
|
||||
for _, m := range matches {
|
||||
username := m[1]
|
||||
if seen[username] {
|
||||
@ -220,12 +222,23 @@ func (s *CommentService) parseMentions(commentID uint, body string) {
|
||||
}
|
||||
seen[username] = true
|
||||
rows, _ := s.repo.SearchUsersByLevel(username, 2, 1, 0)
|
||||
if len(rows) > 0 {
|
||||
_ = s.repo.CreateMention(&model.CommentMention{
|
||||
CommentID: commentID,
|
||||
UID: rows[0].UID,
|
||||
OriginalUsername: username,
|
||||
})
|
||||
if len(rows) == 0 {
|
||||
continue
|
||||
}
|
||||
mentionedUID := rows[0].UID
|
||||
_ = s.repo.CreateMention(&model.CommentMention{
|
||||
CommentID: commentID,
|
||||
UID: mentionedUID,
|
||||
OriginalUsername: username,
|
||||
})
|
||||
|
||||
// 向被@用户发送通知(排除自己@自己、重复通知)
|
||||
if s.notifier != nil && mentionedUID != commenterID && !notified[mentionedUID] {
|
||||
notified[mentionedUID] = true
|
||||
s.notifier.Create(mentionedUID, model.NotifyCommentMention,
|
||||
"新提及",
|
||||
fmt.Sprintf("%s 在评论中 @ 了你", commenterName),
|
||||
&postID, &commentID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ func categoryTypes(category string) []string {
|
||||
case "system":
|
||||
return []string{model.NotifyAuditApproved, model.NotifyAuditRejected, model.NotifyPostApproved, model.NotifyPostRejected, model.NotifyPostLocked, model.NotifyPostUnlocked, model.NotifyLevelUp}
|
||||
case "mention":
|
||||
return []string{model.NotifyComment, model.NotifyCommentReply}
|
||||
return []string{model.NotifyComment, model.NotifyCommentReply, model.NotifyCommentMention}
|
||||
case "like":
|
||||
return []string{model.NotifyLikeAggregated}
|
||||
case "follow":
|
||||
|
||||
Reference in New Issue
Block a user