package daytask import ( "app/commons/model/entity" "app/commons/services" "github.com/gin-gonic/gin" ) // NoticeList 消息列表 func (s *Server) NoticeList(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() noticeType := ctx.QueryString("type", "") // system/task/wallet/team paging := &services.Pagination{ Current: ctx.QueryInt64("current", 1), Size: ctx.QueryInt64("size", 20), } query := db.Model(&entity.DtNotice{}). Where("(user_id = ? OR user_id = 0) AND status = ?", userId, 1) if noticeType != "" { query = query.Where("type = ?", noticeType) } query.Count(&paging.Total) paging.Computer() type NoticeInfo struct { Id int64 `json:"id"` Title string `json:"title"` Content string `json:"content"` Type string `json:"type"` IsRead int8 `json:"isRead"` CreatedAt int64 `json:"createdAt"` } notices := make([]*NoticeInfo, 0) query.Select("id, title, content, type, is_read, created_at"). Order("created_at DESC"). Offset(int(paging.Start)). Limit(int(paging.Size)). Scan(¬ices) // 对于全局通知(user_id=0),批量查询已读状态(避免N+1) unreadIds := make([]int64, 0) for _, n := range notices { if n.IsRead == 0 { unreadIds = append(unreadIds, n.Id) } } if len(unreadIds) > 0 { var readRecords []entity.DtNoticeRead db.Where("user_id = ? AND notice_id IN ?", userId, unreadIds).Find(&readRecords) readMap := make(map[int64]bool) for _, r := range readRecords { readMap[r.NoticeId] = true } for _, n := range notices { if n.IsRead == 0 && readMap[n.Id] { n.IsRead = 1 } } } ctx.OK(gin.H{ "list": notices, "paging": paging, }) } // NoticeRead 标记消息已读 func (s *Server) NoticeRead(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() type Req struct { Id int64 `json:"id" form:"id" binding:"required"` } var req Req if err := c.ShouldBind(&req); err != nil { ctx.Fail("invalid_params") return } // 查询通知 var notice entity.DtNotice if err := db.Where("id = ?", req.Id).First(¬ice).Error; err != nil { ctx.Fail("notice_not_found") return } if notice.UserId == 0 { // 全局通知:写入关联表记录已读 readRecord := &entity.DtNoticeRead{ UserId: userId, NoticeId: req.Id, } db.Where("user_id = ? AND notice_id = ?", userId, req.Id). FirstOrCreate(readRecord) } else { // 个人通知:直接更新 db.Model(&entity.DtNotice{}). Where("id = ? AND user_id = ?", req.Id, userId). Update("is_read", 1) } ctx.OK(gin.H{}) } // NoticeReadAll 标记所有消息已读 func (s *Server) NoticeReadAll(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() noticeType := ctx.QueryString("type", "") // 1. 更新个人通知 personalQuery := db.Model(&entity.DtNotice{}). Where("user_id = ? AND is_read = ?", userId, 0) if noticeType != "" { personalQuery = personalQuery.Where("type = ?", noticeType) } personalQuery.Update("is_read", 1) // 2. 全局通知:查出未读的全局通知,批量写入关联表 globalQuery := db.Model(&entity.DtNotice{}). Where("user_id = 0 AND status = 1") if noticeType != "" { globalQuery = globalQuery.Where("type = ?", noticeType) } var globalNotices []entity.DtNotice globalQuery.Select("id").Find(&globalNotices) for _, n := range globalNotices { readRecord := &entity.DtNoticeRead{ UserId: userId, NoticeId: n.Id, } db.Where("user_id = ? AND notice_id = ?", userId, n.Id). FirstOrCreate(readRecord) } ctx.OK(gin.H{}) } // NoticeUnread 未读消息数量 func (s *Server) NoticeUnread(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() // 个人未读通知数 var personalCount int64 db.Model(&entity.DtNotice{}). Where("user_id = ? AND is_read = ? AND status = ?", userId, 0, 1). Count(&personalCount) // 全局未读通知数(排除已在关联表中标记已读的) var globalCount int64 db.Model(&entity.DtNotice{}). Where("user_id = 0 AND status = 1"). Where("id NOT IN (SELECT notice_id FROM dt_notice_read WHERE user_id = ?)", userId). Count(&globalCount) total := personalCount + globalCount ctx.OK(gin.H{ "personal": personalCount, "global": globalCount, "total": total, }) } // NoticeDelete 删除消息 func (s *Server) NoticeDelete(c *gin.Context) { ctx := s.FromContext(c) db := s.DB() userId := ctx.UserId() type Req struct { Id int64 `json:"id" form:"id" binding:"required"` } var req Req if err := c.ShouldBind(&req); err != nil { ctx.Fail("invalid_params") return } // 只能删除自己的消息(全局通知不可删除) db.Where("id = ? AND user_id = ?", req.Id, userId).Delete(&entity.DtNotice{}) ctx.OK(gin.H{}) }