feat: 实现用户通知系统,包含通知模型、数据操作、业务逻辑及相关API接口。
This commit is contained in:
158
internal/handler/notification_handler.go
Normal file
158
internal/handler/notification_handler.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"accounting-app/internal/models"
|
||||
"accounting-app/internal/service"
|
||||
"accounting-app/pkg/api"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type NotificationHandler struct {
|
||||
service *service.NotificationService
|
||||
}
|
||||
|
||||
func NewNotificationHandler(service *service.NotificationService) *NotificationHandler {
|
||||
return &NotificationHandler{service: service}
|
||||
}
|
||||
|
||||
// GetNotifications returns a list of notifications for the user
|
||||
func (h *NotificationHandler) GetNotifications(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
|
||||
var isRead *bool
|
||||
if val, ok := c.GetQuery("is_read"); ok {
|
||||
parsedVal, err := strconv.ParseBool(val)
|
||||
if err == nil {
|
||||
isRead = &parsedVal
|
||||
}
|
||||
}
|
||||
|
||||
notifications, total, err := h.service.GetNotifications(userID.(uint), page, limit, isRead)
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "FETCH_ERROR", "Failed to fetch notifications")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{
|
||||
"notifications": notifications,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
})
|
||||
}
|
||||
|
||||
// GetUnreadCount returns the number of unread notifications
|
||||
func (h *NotificationHandler) GetUnreadCount(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
count, err := h.service.GetUnreadCount(userID.(uint))
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "FETCH_ERROR", "Failed to count unread notifications")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{
|
||||
"count": count,
|
||||
})
|
||||
}
|
||||
|
||||
// MarkAsRead marks a specific notification as read
|
||||
func (h *NotificationHandler) MarkAsRead(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_ID", "Invalid notification ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.MarkAsRead(uint(id), userID.(uint)); err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "UPDATE_ERROR", "Failed to mark as read")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "Marked as read"})
|
||||
}
|
||||
|
||||
// MarkAllAsRead marks all notifications as read
|
||||
func (h *NotificationHandler) MarkAllAsRead(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.MarkAllAsRead(userID.(uint)); err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "UPDATE_ERROR", "Failed to mark all as read")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "All marked as read"})
|
||||
}
|
||||
|
||||
// CreateNotificationRequest represents the request body for creating a notification (internal/admin use primarily)
|
||||
type CreateNotificationRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
Type string `json:"type" binding:"required"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
|
||||
// CreateNotification creates a new notification (For testing/admin purposes)
|
||||
func (h *NotificationHandler) CreateNotification(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateNotificationRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request")
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.CreateNotification(
|
||||
userID.(uint),
|
||||
req.Title,
|
||||
req.Content,
|
||||
models.NotificationType(req.Type),
|
||||
req.Link,
|
||||
)
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "CREATE_ERROR", "Failed to create notification")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"message": "Notification created"})
|
||||
}
|
||||
|
||||
// RegisterRoutes registers the notification routes
|
||||
func (h *NotificationHandler) RegisterRoutes(r *gin.RouterGroup) {
|
||||
notifications := r.Group("/notifications")
|
||||
{
|
||||
notifications.GET("", h.GetNotifications)
|
||||
notifications.GET("/unread-count", h.GetUnreadCount)
|
||||
notifications.PUT("/:id/read", h.MarkAsRead)
|
||||
notifications.PUT("/read-all", h.MarkAllAsRead)
|
||||
notifications.POST("", h.CreateNotification) // Admin/Internal use
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user